Compare commits
646 Commits
modifier-p
...
buildbot-l
Author | SHA1 | Date | |
---|---|---|---|
2cbc328bdc | |||
314783f2e7 | |||
fb0f0f4d79 | |||
f58f09c9a9 | |||
![]() |
46ae115b88 | ||
![]() |
ba2c039b05 | ||
945d0269e3 | |||
22197d7f8a | |||
26ffed7466 | |||
afd976a3b4 | |||
8bee200e2f | |||
52b125a790 | |||
b6f35531b6 | |||
e16972389e | |||
792cb8bdc7 | |||
755c5c6e4c | |||
4723644e7f | |||
6358c7754c | |||
bf5a656ff6 | |||
11a1ddfd30 | |||
f228a8948b | |||
927448a1da | |||
e9d1d1f725 | |||
2788b0261c | |||
f4f00661a5 | |||
42be3964eb | |||
b5660f71fe | |||
![]() |
5db82be980 | ||
6f0aca7973 | |||
6a302e6845 | |||
9324e1117a | |||
23cc2a2628 | |||
323c5e1e0b | |||
86e41ca775 | |||
ab0d02b704 | |||
4387aff99e | |||
8d3c4aa2d7 | |||
6c7d0aebcb | |||
9f634a195d | |||
![]() |
8c4703127a | ||
d885b1141c | |||
36d6aa428f | |||
63b8cf4518 | |||
38bbd783b3 | |||
039bfe0e05 | |||
aeb4792044 | |||
a3e6b7c2ce | |||
981d7381cd | |||
3562be2bda | |||
db7d370657 | |||
7dbfc864e6 | |||
21c2a64e79 | |||
0949140d36 | |||
8262e37d22 | |||
9693163e2f | |||
9d80e6a6bb | |||
c2ebf3edb4 | |||
67da2bd23a | |||
d67b7f3b52 | |||
613f62d15c | |||
d92e5f8950 | |||
5c9c3a3234 | |||
e60b6f586b | |||
95ee06d068 | |||
d4b9b2c020 | |||
![]() |
03b8173059 | ||
6add0cc88a | |||
438bd82371 | |||
6ac235a6f7 | |||
27783b4ac7 | |||
26cdab02a8 | |||
e0ef574c40 | |||
49d05687be | |||
37820651bb | |||
![]() |
5b03f49302 | ||
![]() |
e93663363e | ||
4e9ed1dae9 | |||
8aaca88402 | |||
2a1af5fa48 | |||
bdbfdce766 | |||
602cfdeac7 | |||
84901f2eda | |||
a6775efb4f | |||
b838a51803 | |||
84f8b47c4c | |||
0291039079 | |||
4c3d51326e | |||
f6394e66ed | |||
a94a05ec19 | |||
24c4d3f1f7 | |||
7556530bac | |||
deb01eb199 | |||
34027506f8 | |||
737b0fd762 | |||
906d93110e | |||
fa7d990f10 | |||
0b3313e532 | |||
4783520bfa | |||
2d8c59ccb9 | |||
9dbe0f9c04 | |||
2917df21ad | |||
a2b7c84ae8 | |||
7860fc9539 | |||
53799d3ed2 | |||
4176adaf96 | |||
55ae55af66 | |||
5d2005cbb5 | |||
![]() |
1d29822fa9 | ||
062a843bfb | |||
![]() |
f28e59bd74 | ||
b29fd7bab8 | |||
421ac266d0 | |||
a71d3bd2df | |||
1fa40c9f8a | |||
4f8a881715 | |||
5d31ef0820 | |||
3aced11d79 | |||
bcf49d13e5 | |||
937d89afba | |||
5024c54271 | |||
583cfe2596 | |||
28f4e5cd6b | |||
febb2351ad | |||
dcdffe719f | |||
b723d38812 | |||
cff688ce7b | |||
bf87df3485 | |||
3118636f81 | |||
9c29803255 | |||
7f1fd1818a | |||
164a49f047 | |||
a351eb0726 | |||
399dbb1aa3 | |||
1cda374906 | |||
13e2337da7 | |||
cb5bfb32ba | |||
81fb08ad57 | |||
76e252ead3 | |||
85cde12bff | |||
2476c47d75 | |||
18bff53c99 | |||
4fc5233467 | |||
9feb0d5f2e | |||
bd6cc282d2 | |||
![]() |
0d2e628964 | ||
9afad1de44 | |||
8e494f7a45 | |||
5a6145f32c | |||
38c9deeb5a | |||
2def6f5568 | |||
784911a4a0 | |||
b51d6e8012 | |||
![]() |
0baa000b85 | ||
3b630bd563 | |||
41bfdeaa53 | |||
b21ba5e579 | |||
3bdfd8c916 | |||
![]() |
fa2c7709ff | ||
6d8b6aec18 | |||
![]() |
340130719f | ||
df8847de6d | |||
59d2dd2237 | |||
4ea92f775e | |||
ff82049642 | |||
e91d581167 | |||
a55eac5107 | |||
9f5fae1f2c | |||
d7b10e5b74 | |||
2350159101 | |||
563670ff9e | |||
fec2b2a809 | |||
4b96f47831 | |||
c1c5dff7c0 | |||
b7b57e7155 | |||
daa815d7fc | |||
84e1e0cf95 | |||
fb68a30af6 | |||
9c1d85117c | |||
06e24f6c91 | |||
4817426b3e | |||
0c98bb75cb | |||
5c48592ccd | |||
e6e67da4ea | |||
4006cd2d2c | |||
9b4e621db0 | |||
26b428186a | |||
d10990af79 | |||
5f4a66c0e8 | |||
d33e715259 | |||
8bcfa0d1fb | |||
f26d7268bf | |||
ea4fa8abb0 | |||
14e313bbb2 | |||
26d0fb3aef | |||
96d657cb84 | |||
8b070b8a71 | |||
65f07a39b5 | |||
9ec6b69ed1 | |||
1ce2457551 | |||
0e75aa44fb | |||
25eb0c9cf4 | |||
ede6e739dd | |||
e707ed43ef | |||
e1da4f09fc | |||
8b119a5524 | |||
da2e71be2f | |||
74c49492c2 | |||
d865ad59fc | |||
e3a420c477 | |||
c7694185c9 | |||
2a72421cfb | |||
2036b9771e | |||
646ef49e19 | |||
2db4a81fe4 | |||
c9d94c2aba | |||
46815753cf | |||
62aa103d48 | |||
af4e68357b | |||
fd0d8c710b | |||
31ad8bda74 | |||
![]() |
2dad5a9754 | ||
230b9eac69 | |||
47ff54b008 | |||
495b0eff9a | |||
b77fc70d13 | |||
dd9c0dbf5e | |||
79c2581bfa | |||
2b9ac1de49 | |||
d0693c160a | |||
fd5c185beb | |||
baa0da3e69 | |||
8903368490 | |||
d69bb06db8 | |||
d3283ef121 | |||
6431b11381 | |||
b30df982d2 | |||
64a584b38a | |||
6b53e0adbc | |||
cdb69c20e1 | |||
0c4f4de23b | |||
bcc086584f | |||
ec776f18ff | |||
eace5903cb | |||
2ad8e16c2d | |||
0dced1af34 | |||
b468023aa1 | |||
5cfbc722d0 | |||
c2ab069dfc | |||
ac0852cea0 | |||
ba380fc0bf | |||
baff05ad1c | |||
ec7510b458 | |||
560a73610b | |||
255638d223 | |||
2b522e3345 | |||
0f7851ee79 | |||
b4e1571d0b | |||
c78b831e69 | |||
e761d0bdc9 | |||
ff0df7c546 | |||
9951858942 | |||
9fe64948ab | |||
6fec2e4db0 | |||
d645525dae | |||
3cfb687b55 | |||
23b5e10dbd | |||
669befdfbe | |||
0a3bde6300 | |||
88157b9efb | |||
073ab4703e | |||
756e664e4f | |||
e59712b7c8 | |||
e389c05410 | |||
a6c59863d3 | |||
dd328be0f0 | |||
074929d1c5 | |||
9b3dfbe651 | |||
be0622533d | |||
6f5a9dd8de | |||
5c8e349c28 | |||
d295261330 | |||
be8f2c698e | |||
1daaac75b5 | |||
31dd80e0de | |||
a9e5e58e16 | |||
5b9bb688e7 | |||
49234c15e2 | |||
c26abd1c29 | |||
b0449cac66 | |||
d82c3d8615 | |||
5fbbe1fca9 | |||
65006bfaf4 | |||
ede1a247d8 | |||
11a390e85e | |||
f3a8192ef7 | |||
2dd60e6c2c | |||
1e0426da7c | |||
9ef5cc44a6 | |||
56f9529775 | |||
f345625ded | |||
adcb7a2ce7 | |||
8b59b97c10 | |||
f7bbc7cdbb | |||
27972c4225 | |||
4284ddefab | |||
bab2b02507 | |||
6d639a606c | |||
![]() |
23f8ab4250 | ||
![]() |
0aa7c11788 | ||
![]() |
8f97a64dec | ||
439b40e601 | |||
![]() |
cc3e808ab4 | ||
072a224a28 | |||
ef8aca65d8 | |||
![]() |
bbb2e0614f | ||
87ceff3d1b | |||
13a5b954c3 | |||
309cfbceaa | |||
3a3708cefb | |||
![]() |
c24b1c060d | ||
4040cb438f | |||
ed68fee665 | |||
374e412813 | |||
3f6f89a06b | |||
3f89322f08 | |||
bdb49890cb | |||
fd65055b69 | |||
6703c7f7f1 | |||
716a8241d3 | |||
a573d7e8a1 | |||
58f3fabb97 | |||
51bf04383a | |||
![]() |
2fdca5bd19 | ||
9335daac2a | |||
73d3f51c16 | |||
15dda0115c | |||
3cea42ce29 | |||
9fbbd25e2a | |||
25d2222c30 | |||
fdfe85c616 | |||
bfaa41c00d | |||
336a8f283f | |||
b175bb2503 | |||
41158a91f2 | |||
461ba2c74c | |||
4a68bf2078 | |||
c94a1f5349 | |||
6223385043 | |||
7117ed9691 | |||
5726dec0e0 | |||
6c76a782e9 | |||
b0de36a5a3 | |||
508e33842b | |||
e2fc9a88bc | |||
85c6f0b472 | |||
![]() |
961fa2251e | ||
c877c3b8f6 | |||
3d570f7e1f | |||
99436acde8 | |||
2c41c8e94f | |||
207338bb58 | |||
d1ef5146d7 | |||
1de0e13af6 | |||
fed101a7be | |||
c7d940278b | |||
e50f1ddc65 | |||
54e3487c9e | |||
b10b7cdb43 | |||
d8c2092b15 | |||
ace3268482 | |||
b7c34c889b | |||
f9d138be51 | |||
8ffb006077 | |||
c309177edd | |||
ba97da21ac | |||
d6e07a7cd3 | |||
5db1ae2605 | |||
2d866d77ae | |||
3752c44b44 | |||
566b4f126d | |||
26e5718e29 | |||
![]() |
19c7b5f45a | ||
61fa710aa3 | |||
f8c8a5c092 | |||
9215b5d869 | |||
56d0df51a3 | |||
f2b5f731d5 | |||
0de14fbe78 | |||
3fc5826f7c | |||
91117cad0f | |||
b4ba27f026 | |||
a7f1c68938 | |||
8ce1a60262 | |||
2d9ab46e0b | |||
bb58d3d8e2 | |||
![]() |
d994391e0c | ||
73ffb3e067 | |||
d7152244f8 | |||
92c5b12df6 | |||
874af5301c | |||
466e716495 | |||
ab72cd2fc1 | |||
a089286d7b | |||
bb4cef71ee | |||
702e00f910 | |||
ec963d9d7d | |||
fb7d8e2f4b | |||
0ded6f5525 | |||
254f164b27 | |||
15083d9e1e | |||
f4c0ea1d29 | |||
e15f85f23d | |||
ce7a5a2376 | |||
a24cd69d78 | |||
eaa44afe70 | |||
27fb75fec2 | |||
334e5005f4 | |||
71363dd79c | |||
f84414d6e1 | |||
e18d6f5206 | |||
f6b23c63e1 | |||
9905f5725c | |||
df25d3c2a3 | |||
b50d01cbac | |||
3ceb9faf1a | |||
![]() |
59b523c3c9 | ||
697b1736ef | |||
1a448c66ed | |||
89b7f785e6 | |||
16d09a5864 | |||
28d77f9354 | |||
90010c3e04 | |||
2193e28dfc | |||
e9a7f4d389 | |||
1f5f3b5588 | |||
3f5b295084 | |||
7ae9227794 | |||
b3b445979e | |||
8c3dd6d83d | |||
0f78a57904 | |||
31ae833811 | |||
171c4fb238 | |||
9e70129952 | |||
f382109f38 | |||
2dff08c8ce | |||
f106369ce8 | |||
0d744cf673 | |||
0ae7883d7d | |||
69c3d9804f | |||
084c5d6c7e | |||
b1ce4ca40c | |||
fade37ff07 | |||
5a77f643f4 | |||
d093f61667 | |||
642b19c8b8 | |||
41f0697501 | |||
1ee32ea228 | |||
0479c28ddd | |||
f1e5fd030a | |||
b89898cbd3 | |||
d56444392f | |||
3aadf68b88 | |||
d5954ef11c | |||
722adcfc48 | |||
52b8d668f4 | |||
44f7852660 | |||
667ef9917f | |||
6899cb3c07 | |||
64bf179a17 | |||
55ebf174bc | |||
e36c05b3d1 | |||
dbf96e6252 | |||
a5e176a8ed | |||
46e4cdf788 | |||
099d47f8a3 | |||
502e6bd839 | |||
3ada1949f8 | |||
aab165b575 | |||
978e2b6f98 | |||
44f4eaf13b | |||
3aa1143d57 | |||
790d942b69 | |||
229ed078d1 | |||
f7f3b2d318 | |||
67a822e086 | |||
47f98a38d0 | |||
8df99b1c0c | |||
ac16d56aa8 | |||
d8206602fe | |||
18ccf328ac | |||
e079bf6996 | |||
ffa23b6c77 | |||
a874cec02b | |||
eacdcb2dd8 | |||
d6ef9c157a | |||
bcb2b8ab57 | |||
4cfdd10c2b | |||
c1c02f45f7 | |||
2e0ac1e0c4 | |||
e590526af6 | |||
9bfd78ae14 | |||
ddf4b909de | |||
13f591d400 | |||
c84fee1ffe | |||
ad6cccf058 | |||
514f80b0c4 | |||
26c0ca3aa7 | |||
a2c4e5d222 | |||
fc7c34e380 | |||
25b8dedfb4 | |||
8591ee748f | |||
70c061ee0a | |||
7dae6eb5a2 | |||
1dfd262f2d | |||
4892470a47 | |||
ba312bc8a7 | |||
3ff9769762 | |||
f9be5374ac | |||
c7b03fe9c0 | |||
efb1bf80df | |||
1b2a24aae0 | |||
16652185ce | |||
94fba47513 | |||
9e307117f8 | |||
2c435cf249 | |||
2e5ef864ab | |||
25a1ed993a | |||
d3de5d7ca5 | |||
4365de3870 | |||
f721308bd0 | |||
2c2fd9f036 | |||
bc7a4b126a | |||
e54058b121 | |||
76d50c51a3 | |||
21d862494b | |||
7d7090710c | |||
38c9573b23 | |||
d2587f6f93 | |||
![]() |
a64b8aca39 | ||
f72419b9ae | |||
a76542cbbf | |||
4db63b6486 | |||
6a0ebb8088 | |||
d97cb98b11 | |||
bf1e5a2133 | |||
b6981d9e48 | |||
eaff606f2d | |||
89bde99674 | |||
![]() |
624994caa2 | ||
![]() |
df1ff76ee2 | ||
0945a79ed1 | |||
![]() |
ab8a691431 | ||
![]() |
3c717a631b | ||
ec25084f5a | |||
eadbdf170a | |||
cf42721fe2 | |||
046afacbc6 | |||
73f8dd0f4c | |||
2797a63a66 | |||
ee61c1fe22 | |||
0d59a643aa | |||
0102b9d47e | |||
76ebc608af | |||
0c38436227 | |||
ece7ebb3a8 | |||
fbf6eb509a | |||
b358a92faf | |||
1d6529873f | |||
bf8b62e874 | |||
![]() |
24d77e7db7 | ||
caa1b16acc | |||
4155f8dc21 | |||
9464260ed7 | |||
cbd894e5a8 | |||
725cc959c7 | |||
b325ecef9c | |||
b29b1c4ef2 | |||
23d0361b30 | |||
fe3ca3f6ce | |||
2a51feff99 | |||
827959ff98 | |||
dd4071b379 | |||
c5a0ce1ade | |||
ca10903299 | |||
75aac463e7 | |||
1754828e33 | |||
9f5833798c | |||
a35de34eb7 | |||
dea2c3f256 | |||
098008f42d | |||
fd8d245e6a | |||
b586f801fc | |||
![]() |
5dca72dfc9 | ||
![]() |
091d801e9f | ||
b1f9799508 | |||
0981b55182 | |||
cfff8aa067 | |||
dc80fe5a3f | |||
7e43bbb790 | |||
9f5cc128d9 | |||
326db1b7cd | |||
9cc0597556 | |||
f8696742bb | |||
fd14d1cceb | |||
a809631ff2 | |||
f12fe3c23e | |||
16595b9ea1 | |||
5549fa5466 | |||
f79856f9fb | |||
24d39620fb | |||
c02baf8b50 | |||
c73ee8d998 | |||
526e8a3da1 | |||
a03ebe9431 | |||
a61ba6c73d | |||
3d18bd5c51 | |||
49af2f85c3 | |||
a364032dff | |||
e44045745d | |||
e22098616c | |||
![]() |
ed00b5def6 | ||
9385d887d1 | |||
95aa8ffed5 | |||
665acd2903 | |||
f028760b83 | |||
3f648f5b42 | |||
e43a948a2c | |||
e916817520 | |||
cc064acf0f | |||
a76fc2f7ed | |||
2c463a8250 | |||
0439094105 | |||
bfa5eceb89 | |||
faf5f7b63d | |||
63930c41bc | |||
0621c13b3e | |||
14bd92b12f | |||
91462fbb31 | |||
4f314ee5b9 | |||
eee35ebdfb | |||
b05fa123d7 | |||
474b288933 | |||
20658e6a29 | |||
4b39de677d | |||
84d4447bc5 | |||
4c172f7ca6 |
@@ -278,7 +278,6 @@ option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd
|
||||
|
||||
# Alembic support
|
||||
option(WITH_ALEMBIC "Enable Alembic Support" ON)
|
||||
option(WITH_ALEMBIC_HDF5 "Enable Legacy Alembic Support (not officially supported)" OFF)
|
||||
|
||||
# Universal Scene Description support
|
||||
option(WITH_USD "Enable Universal Scene Description (USD) Support" ON)
|
||||
@@ -322,14 +321,6 @@ mark_as_advanced(WITH_SYSTEM_GLOG)
|
||||
# Freestyle
|
||||
option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
|
||||
|
||||
# New object types
|
||||
option(WITH_NEW_OBJECT_TYPES "Enable new hair and pointcloud objects (use for development only, don't save in files)" OFF)
|
||||
mark_as_advanced(WITH_NEW_OBJECT_TYPES)
|
||||
|
||||
# New simulation data block
|
||||
option(WITH_NEW_SIMULATION_TYPE "Enable simulation data block (use for development only, don't save in files)" OFF)
|
||||
mark_as_advanced(WITH_NEW_SIMULATION_TYPE)
|
||||
|
||||
# Misc
|
||||
if(WIN32)
|
||||
option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON)
|
||||
@@ -371,7 +362,7 @@ option(WITH_CYCLES "Enable Cycles Render Engine" ON)
|
||||
option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF)
|
||||
option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF)
|
||||
option(WITH_CYCLES_OSL "Build Cycles with OSL support" ON)
|
||||
option(WITH_CYCLES_EMBREE "Build Cycles with Embree support" OFF)
|
||||
option(WITH_CYCLES_EMBREE "Build Cycles with Embree support" ON)
|
||||
option(WITH_CYCLES_CUDA_BINARIES "Build Cycles CUDA binaries" OFF)
|
||||
option(WITH_CYCLES_CUBIN_COMPILER "Build cubins with nvrtc based compiler instead of nvcc" OFF)
|
||||
option(WITH_CYCLES_CUDA_BUILD_SERIAL "Build cubins one after another (useful on machines with limited RAM)" OFF)
|
||||
@@ -655,6 +646,7 @@ if(WITH_BOOST AND NOT (WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
|
||||
set(WITH_BOOST OFF)
|
||||
endif()
|
||||
|
||||
set_and_warn_dependency(WITH_TBB WITH_CYCLES OFF)
|
||||
set_and_warn_dependency(WITH_TBB WITH_USD OFF)
|
||||
set_and_warn_dependency(WITH_TBB WITH_OPENIMAGEDENOISE OFF)
|
||||
set_and_warn_dependency(WITH_TBB WITH_OPENVDB OFF)
|
||||
@@ -1246,7 +1238,7 @@ endif()
|
||||
|
||||
if(WITH_LIBMV)
|
||||
# We always have C++11 which includes unordered_map.
|
||||
set(CERES_DEFINES -DCERES_STD_UNORDERED_MAP)
|
||||
set(CERES_DEFINES "-DCERES_STD_UNORDERED_MAP;-DCERES_USE_CXX_THREADS")
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
@@ -1562,20 +1554,15 @@ if(WITH_PYTHON)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# MSVC needs to be tested first, since clang on windows will
|
||||
# match the compiler test below but clang-cl does not accept -std=c++11
|
||||
# since it is on by default and cannot be turned off.
|
||||
#
|
||||
# Nothing special is needed, C++11 features are available by default.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17")
|
||||
elseif(
|
||||
CMAKE_COMPILER_IS_GNUCC OR
|
||||
CMAKE_C_COMPILER_ID MATCHES "Clang" OR
|
||||
CMAKE_C_COMPILER_ID MATCHES "Intel"
|
||||
)
|
||||
# TODO(sergey): Do we want c++11 or gnu-c++11 here?
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown compiler ${CMAKE_C_COMPILER_ID}, can't enable C++11 build")
|
||||
message(FATAL_ERROR "Unknown compiler ${CMAKE_C_COMPILER_ID}, can't enable C++17 build")
|
||||
endif()
|
||||
|
||||
# Visual Studio has all standards it supports available by default
|
||||
|
10
GNUmakefile
10
GNUmakefile
@@ -32,6 +32,7 @@ Convenience Targets
|
||||
* debug: Build a debug binary.
|
||||
* full: Enable all supported dependencies & options.
|
||||
* lite: Disable non essential features for a smaller binary and faster build.
|
||||
* release Complete build with all options enabled including CUDA and Optix, matching the releases on blender.org
|
||||
* headless: Build without an interface (renderfarm or server automation).
|
||||
* cycles: Build Cycles standalone only, without Blender.
|
||||
* bpy: Build as a python module which can be loaded from python directly.
|
||||
@@ -141,6 +142,10 @@ Information
|
||||
endef
|
||||
# HELP_TEXT (end)
|
||||
|
||||
# This makefile is not meant for Windows
|
||||
ifeq ($(OS),Windows_NT)
|
||||
$(error On Windows, use "cmd //c make.bat" instead of "make")
|
||||
endif
|
||||
|
||||
# System Vars
|
||||
OS:=$(shell uname -s)
|
||||
@@ -207,6 +212,10 @@ ifneq "$(findstring lite, $(MAKECMDGOALS))" ""
|
||||
BUILD_DIR:=$(BUILD_DIR)_lite
|
||||
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_lite.cmake" $(CMAKE_CONFIG_ARGS)
|
||||
endif
|
||||
ifneq "$(findstring release, $(MAKECMDGOALS))" ""
|
||||
BUILD_DIR:=$(BUILD_DIR)_release
|
||||
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/blender_release.cmake" $(CMAKE_CONFIG_ARGS)
|
||||
endif
|
||||
ifneq "$(findstring cycles, $(MAKECMDGOALS))" ""
|
||||
BUILD_DIR:=$(BUILD_DIR)_cycles
|
||||
CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/cycles_standalone.cmake" $(CMAKE_CONFIG_ARGS)
|
||||
@@ -317,6 +326,7 @@ all: .FORCE
|
||||
debug: all
|
||||
full: all
|
||||
lite: all
|
||||
release: all
|
||||
cycles: all
|
||||
headless: all
|
||||
bpy: all
|
||||
|
@@ -48,11 +48,7 @@ include(cmake/options.cmake)
|
||||
include(cmake/versions.cmake)
|
||||
|
||||
if(ENABLE_MINGW64)
|
||||
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
include(cmake/setup_mingw64.cmake)
|
||||
else()
|
||||
include(cmake/setup_mingw32.cmake)
|
||||
endif()
|
||||
include(cmake/setup_mingw64.cmake)
|
||||
else()
|
||||
set(mingw_LIBDIR ${LIBDIR})
|
||||
endif()
|
||||
@@ -97,17 +93,18 @@ if(UNIX)
|
||||
else()
|
||||
include(cmake/pugixml.cmake)
|
||||
endif()
|
||||
include(cmake/ispc.cmake)
|
||||
include(cmake/openimagedenoise.cmake)
|
||||
include(cmake/embree.cmake)
|
||||
include(cmake/xr_openxr.cmake)
|
||||
if(NOT APPLE)
|
||||
include(cmake/xr_openxr.cmake)
|
||||
endif()
|
||||
|
||||
if(WITH_WEBP)
|
||||
include(cmake/webp.cmake)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# HMD branch deps
|
||||
include(cmake/hidapi.cmake)
|
||||
# OCIO deps
|
||||
include(cmake/tinyxml.cmake)
|
||||
include(cmake/yamlcpp.cmake)
|
||||
|
@@ -16,16 +16,6 @@
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
if(ALEMBIC_HDF5)
|
||||
set(ALEMBIC_HDF5_HL)
|
||||
# in debug mode we do not build HDF5_hdf5_hl_LIBRARY which makes cmake really
|
||||
# unhappy, stub it with the debug mode lib. it's not linking it in at this
|
||||
# point in time anyhow
|
||||
if(BUILD_MODE STREQUAL Debug)
|
||||
set(ALEMBIC_HDF5_HL -DHDF5_hdf5_hl_LIBRARY=${LIBDIR}/hdf5/lib/libhdf5_hl_D.${LIBEXT})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(ALEMBIC_EXTRA_ARGS
|
||||
-DBUILDSTATIC=ON
|
||||
-DLINKSTATIC=ON
|
||||
@@ -53,7 +43,6 @@ set(ALEMBIC_EXTRA_ARGS
|
||||
-DUSE_PRMAN=0
|
||||
-DUSE_HDF5=Off
|
||||
-DUSE_STATIC_HDF5=Off
|
||||
-DHDF5_ROOT=${LIBDIR}/hdf5
|
||||
-DUSE_TESTS=Off
|
||||
-DALEMBIC_NO_OPENGL=1
|
||||
-DUSE_BINARIES=ON
|
||||
@@ -62,7 +51,6 @@ set(ALEMBIC_EXTRA_ARGS
|
||||
-DGLUT_INCLUDE_DIR=""
|
||||
-DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY}
|
||||
-DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include/
|
||||
${ALEMBIC_HDF5_HL}
|
||||
)
|
||||
|
||||
ExternalProject_Add(external_alembic
|
||||
|
@@ -51,6 +51,7 @@ ExternalProject_Add(external_embree
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH MD5=${EMBREE_HASH}
|
||||
PREFIX ${BUILD_DIR}/embree
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/embree/src/external_embree < ${PATCH_DIR}/embree.diff
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/embree ${DEFAULT_CMAKE_FLAGS} ${EMBREE_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/embree
|
||||
)
|
||||
|
@@ -43,21 +43,10 @@ if(BUILD_MODE STREQUAL Release)
|
||||
# tiff
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/tiff/lib/tiff.lib ${HARVEST_TARGET}/tiff/lib/libtiff.lib &&
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/tiff/include/ ${HARVEST_TARGET}/tiff/include/ &&
|
||||
# hidapi
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/hidapi/ ${HARVEST_TARGET}/hidapi/
|
||||
DEPENDS
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BUILD_MODE STREQUAL Debug)
|
||||
add_custom_target(Harvest_Debug_Results
|
||||
COMMAND
|
||||
# hdf5
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/hdf5/lib ${HARVEST_TARGET}/hdf5/lib &&
|
||||
DEPENDS Package_Python
|
||||
)
|
||||
endif()
|
||||
|
||||
else(WIN32)
|
||||
|
||||
function(harvest from to)
|
||||
|
@@ -1,42 +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.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(HDF5_EXTRA_ARGS
|
||||
-DHDF5_ENABLE_THREADSAFE=Off
|
||||
-DHDF5_BUILD_CPP_LIB=Off
|
||||
-DBUILD_TESTING=Off
|
||||
-DHDF5_BUILD_TOOLS=Off
|
||||
-DHDF5_BUILD_EXAMPLES=Off
|
||||
-DHDF5_BUILD_HL_LIB=On
|
||||
-DBUILD_STATIC_CRT_LIBS=On
|
||||
-DBUILD_SHARED_LIBS=On
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(HDF5_PATCH ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/hdf5/src/external_hdf5 < ${PATCH_DIR}/hdf5.diff)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(external_hdf5
|
||||
URL ${HDF5_URI}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH MD5=${HDF5_HASH}
|
||||
PREFIX ${BUILD_DIR}/hdf5
|
||||
PATCH_COMMAND ${HDF5_PATCH}
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/hdf5 ${HDF5_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/hdf5
|
||||
)
|
63
build_files/build_environment/cmake/ispc.cmake
Normal file
63
build_files/build_environment/cmake/ispc.cmake
Normal file
@@ -0,0 +1,63 @@
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
if(WIN32)
|
||||
set(ISPC_EXTRA_ARGS_WIN
|
||||
-DFLEX_EXECUTABLE=${LIBDIR}/flexbison/win_flex.exe
|
||||
-DBISON_EXECUTABLE=${LIBDIR}/flexbison/win_bison.exe
|
||||
-DM4_EXECUTABLE=${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/m4.exe
|
||||
)
|
||||
endif()
|
||||
|
||||
set(ISPC_EXTRA_ARGS
|
||||
-DARM_ENABLED=Off
|
||||
-DISPC_NO_DUMPS=On
|
||||
-DISPC_INCLUDE_EXAMPLES=Off
|
||||
-DISPC_INCLUDE_TESTS=Off
|
||||
-DLLVM_ROOT=${LIBDIR}/llvm/lib/cmake/llvm
|
||||
-DLLVM_LIBRARY_DIR=${LIBDIR}/llvm/lib
|
||||
-DCLANG_EXECUTABLE=${LIBDIR}/clang/bin/clang
|
||||
-DISPC_INCLUDE_TESTS=Off
|
||||
-DCLANG_LIBRARY_DIR=${LIBDIR}/clang/lib
|
||||
-DCLANG_INCLUDE_DIRS=${LIBDIR}/clang/include
|
||||
${ISPC_EXTRA_ARGS_WIN}
|
||||
)
|
||||
|
||||
ExternalProject_Add(external_ispc
|
||||
URL ${ISPC_URI}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH MD5=${ISPC_HASH}
|
||||
PREFIX ${BUILD_DIR}/ispc
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/ispc/src/external_ispc < ${PATCH_DIR}/ispc.diff
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/ispc -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${ISPC_EXTRA_ARGS} ${BUILD_DIR}/ispc/src/external_ispc
|
||||
INSTALL_DIR ${LIBDIR}/ispc
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
external_ispc
|
||||
ll
|
||||
external_clang
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
add_dependencies(
|
||||
external_ispc
|
||||
external_flexbison
|
||||
)
|
||||
endif()
|
||||
|
@@ -18,26 +18,41 @@
|
||||
|
||||
|
||||
set(OIDN_EXTRA_ARGS
|
||||
-DWITH_EXAMPLE=OFF
|
||||
-DWITH_TEST=OFF
|
||||
-DOIDN_APPS=OFF
|
||||
-DTBB_ROOT=${LIBDIR}/tbb
|
||||
-DTBB_STATIC_LIB=${TBB_STATIC_LIBRARY}
|
||||
-DOIDN_STATIC_LIB=ON
|
||||
-DOIDN_STATIC_RUNTIME=OFF
|
||||
-DISPC_EXECUTABLE=${LIBDIR}/ispc/bin/ispc
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(OIDN_EXTRA_ARGS
|
||||
${OIDN_EXTRA_ARGS}
|
||||
-DTBB_DEBUG_LIBRARY=${LIBDIR}/tbb/lib/tbb.lib
|
||||
-DTBB_DEBUG_LIBRARY_MALLOC=${LIBDIR}/tbb/lib/tbbmalloc.lib
|
||||
)
|
||||
else()
|
||||
set(OIDN_EXTRA_ARGS
|
||||
${OIDN_EXTRA_ARGS}
|
||||
-Dtbb_LIBRARY_RELEASE=${LIBDIR}/tbb/lib/tbb_static.a
|
||||
-Dtbbmalloc_LIBRARY_RELEASE=${LIBDIR}/tbb/lib/tbbmalloc_static.a
|
||||
)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(external_openimagedenoise
|
||||
URL ${OIDN_URI}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH MD5=${OIDN_HASH}
|
||||
PREFIX ${BUILD_DIR}/openimagedenoise
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openimagedenoise ${DEFAULT_CMAKE_FLAGS} ${OIDN_EXTRA_ARGS}
|
||||
PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/openimagedenoise/src/external_openimagedenoise < ${PATCH_DIR}/openimagedenoise.diff
|
||||
INSTALL_DIR ${LIBDIR}/openimagedenoise
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
external_openimagedenoise
|
||||
external_tbb
|
||||
external_ispc
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
@@ -46,7 +61,7 @@ if(WIN32)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openimagedenoise/include ${HARVEST_TARGET}/openimagedenoise/include
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/openimagedenoise.lib ${HARVEST_TARGET}/openimagedenoise/lib/openimagedenoise.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/common.lib ${HARVEST_TARGET}/openimagedenoise/lib/common.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/mkldnn.lib ${HARVEST_TARGET}/openimagedenoise/lib/mkldnn.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/dnnl.lib ${HARVEST_TARGET}/openimagedenoise/lib/dnnl.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
@@ -54,7 +69,7 @@ if(WIN32)
|
||||
ExternalProject_Add_Step(external_openimagedenoise after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/openimagedenoise.lib ${HARVEST_TARGET}/openimagedenoise/lib/openimagedenoise_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/common.lib ${HARVEST_TARGET}/openimagedenoise/lib/common_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/mkldnn.lib ${HARVEST_TARGET}/openimagedenoise/lib/mkldnn_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimagedenoise/lib/dnnl.lib ${HARVEST_TARGET}/openimagedenoise/lib/dnnl_d.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
@@ -17,7 +17,7 @@
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
if(WIN32)
|
||||
option(ENABLE_MINGW64 "Enable building of ffmpeg/iconv/libsndfile/lapack/fftw3 by installing mingw64" ON)
|
||||
option(ENABLE_MINGW64 "Enable building of ffmpeg/iconv/libsndfile/fftw3 by installing mingw64" ON)
|
||||
endif()
|
||||
option(WITH_WEBP "Enable building of oiio with webp support" OFF)
|
||||
set(MAKE_THREADS 1 CACHE STRING "Number of threads to run make with")
|
||||
@@ -45,11 +45,7 @@ message("PATCH_DIR = ${PATCH_DIR}")
|
||||
message("BUILD_DIR = ${BUILD_DIR}")
|
||||
|
||||
if(WIN32)
|
||||
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
set(PATCH_CMD ${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/patch.exe)
|
||||
else()
|
||||
set(PATCH_CMD ${DOWNLOAD_DIR}/mingw/mingw32/msys/1.0/bin/patch.exe)
|
||||
endif()
|
||||
set(PATCH_CMD ${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/patch.exe)
|
||||
set(LIBEXT ".lib")
|
||||
set(LIBPREFIX "")
|
||||
|
||||
@@ -82,17 +78,10 @@ if(WIN32)
|
||||
set(PLATFORM_CXX_FLAGS)
|
||||
set(PLATFORM_CMAKE_FLAGS)
|
||||
|
||||
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
set(MINGW_PATH ${DOWNLOAD_DIR}/mingw/mingw64)
|
||||
set(MINGW_SHELL ming64sh.cmd)
|
||||
set(PERL_SHELL ${DOWNLOAD_DIR}/perl/portableshell.bat)
|
||||
set(MINGW_HOST x86_64-w64-mingw32)
|
||||
else()
|
||||
set(MINGW_PATH ${DOWNLOAD_DIR}/mingw/mingw32)
|
||||
set(MINGW_SHELL ming32sh.cmd)
|
||||
set(PERL_SHELL ${DOWNLOAD_DIR}/perl32/portableshell.bat)
|
||||
set(MINGW_HOST i686-w64-mingw32)
|
||||
endif()
|
||||
set(MINGW_PATH ${DOWNLOAD_DIR}/mingw/mingw64)
|
||||
set(MINGW_SHELL ming64sh.cmd)
|
||||
set(PERL_SHELL ${DOWNLOAD_DIR}/perl/portableshell.bat)
|
||||
set(MINGW_HOST x86_64-w64-mingw32)
|
||||
|
||||
set(CONFIGURE_ENV
|
||||
cd ${MINGW_PATH} &&
|
||||
|
@@ -75,6 +75,7 @@ set(OSL_EXTRA_ARGS
|
||||
-DUSE_LLVM_BITCODE=OFF
|
||||
-DUSE_PARTIO=OFF
|
||||
-DUSE_QT=OFF
|
||||
-DINSTALL_DOCS=OFF
|
||||
${OSL_SIMD_FLAGS}
|
||||
-DPARTIO_LIBRARIES=
|
||||
)
|
||||
|
@@ -1,227 +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.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
####################################################################################################################
|
||||
# Mingw32 Builds
|
||||
####################################################################################################################
|
||||
# This installs mingw32+msys to compile ffmpeg/iconv/libsndfile/lapack/fftw3
|
||||
####################################################################################################################
|
||||
|
||||
message("LIBDIR = ${LIBDIR}")
|
||||
macro(cmake_to_msys_path MsysPath ResultingPath)
|
||||
string(REPLACE ":" "" TmpPath "${MsysPath}")
|
||||
string(SUBSTRING ${TmpPath} 0 1 Drive)
|
||||
string(SUBSTRING ${TmpPath} 1 255 PathPart)
|
||||
string(TOLOWER ${Drive} LowerDrive)
|
||||
string(CONCAT ${ResultingPath} "/" ${LowerDrive} ${PathPart})
|
||||
endmacro()
|
||||
cmake_to_msys_path(${LIBDIR} mingw_LIBDIR)
|
||||
message("mingw_LIBDIR = ${mingw_LIBDIR}")
|
||||
|
||||
message("Checking for mingw32")
|
||||
# download mingw32
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/i686-4.9.4-release-win32-sjlj-rt_v5-rev0.7z")
|
||||
message("Downloading mingw32")
|
||||
file(DOWNLOAD "https://astuteinternet.dl.sourceforge.net/project/mingw-w64/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.4/threads-win32/sjlj/i686-4.9.4-release-win32-sjlj-rt_v5-rev0.7z" "${DOWNLOAD_DIR}/i686-4.9.4-release-win32-sjlj-rt_v5-rev0.7z")
|
||||
endif()
|
||||
|
||||
# make mingw root directory
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${DOWNLOAD_DIR}/mingw
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# extract mingw32
|
||||
if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/ming32sh.cmd") AND (EXISTS "${DOWNLOAD_DIR}/i686-4.9.4-release-win32-sjlj-rt_v5-rev0.7z"))
|
||||
message("Extracting mingw32")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/i686-4.9.4-release-win32-sjlj-rt_v5-rev0.7z
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw
|
||||
)
|
||||
endif()
|
||||
|
||||
message("Checking for pkg-config")
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip")
|
||||
message("Downloading pkg-config")
|
||||
file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/pkgconfiglite/0.28-1/pkg-config-lite-0.28-1_bin-win32.zip" "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip")
|
||||
endif()
|
||||
|
||||
# extract pkgconfig
|
||||
if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/pkg-config.exe") AND (EXISTS "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip"))
|
||||
message("Extracting pkg-config")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1_bin-win32.zip"
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/pkg-config-lite-0.28-1/bin/pkg-config.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/pkg-config.exe"
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
message("Checking for nasm")
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/nasm-2.13.02-win32.zip")
|
||||
message("Downloading nasm")
|
||||
file(DOWNLOAD "http://www.nasm.us/pub/nasm/releasebuilds/2.13.02/win32/nasm-2.13.02-win32.zip" "${DOWNLOAD_DIR}/nasm-2.13.02-win32.zip")
|
||||
endif()
|
||||
|
||||
# extract nasm
|
||||
if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe") AND (EXISTS "${DOWNLOAD_DIR}/nasm-2.13.02-win32.zip"))
|
||||
message("Extracting nasm")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/nasm-2.13.02-win32.zip"
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/
|
||||
)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/nasm-2.13.02/nasm.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe"
|
||||
)
|
||||
|
||||
endif()
|
||||
SET(NASM_PATH ${DOWNLOAD_DIR}/mingw/mingw32/bin/nasm.exe)
|
||||
message("Checking for mingwGet")
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip")
|
||||
message("Downloading mingw-get")
|
||||
file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/mingw/Installer/mingw-get/mingw-get-0.6.2-beta-20131004-1/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip" "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip")
|
||||
endif()
|
||||
|
||||
# extract mingw_get
|
||||
if((NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/mingw-get.exe") AND (EXISTS "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip"))
|
||||
message("Extracting mingw-get")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar jxf "${DOWNLOAD_DIR}/mingw-get-0.6.2-mingw32-beta-20131004-1-bin.zip"
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw/mingw32/
|
||||
)
|
||||
endif()
|
||||
|
||||
if((EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/mingw-get.exe") AND (NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/msys/1.0/bin/make.exe"))
|
||||
message("Installing MSYS")
|
||||
execute_process(
|
||||
COMMAND ${DOWNLOAD_DIR}/mingw/mingw32/bin/mingw-get install msys msys-patch
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw/mingw32/bin/
|
||||
)
|
||||
endif()
|
||||
|
||||
if((EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/mingw-get.exe") AND (NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/msys/1.0/bin/mktemp.exe"))
|
||||
message("Installing mktemp")
|
||||
execute_process(
|
||||
COMMAND ${DOWNLOAD_DIR}/mingw/mingw32/bin/mingw-get install msys msys-mktemp
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw/mingw32/bin/
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
message("Checking for CoreUtils")
|
||||
# download old core_utils for pr.exe (ffmpeg needs it to build)
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2")
|
||||
message("Downloading CoreUtils 5.97")
|
||||
file(DOWNLOAD "https://nchc.dl.sourceforge.net/project/mingw/MSYS/Base/msys-core/_obsolete/coreutils-5.97-MSYS-1.0.11-2/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2" "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2")
|
||||
endif()
|
||||
|
||||
if((EXISTS "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2") AND (NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/msys/1.0/bin/pr.exe"))
|
||||
message("Installing pr from CoreUtils 5.97")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${DOWNLOAD_DIR}/tmp_coreutils
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/tmp_coreutils/
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${DOWNLOAD_DIR}/tmp_coreutils/coreutils-5.97/bin/pr.exe "${DOWNLOAD_DIR}/mingw/mingw32/msys/1.0/bin/pr.exe"
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/tmp_coreutils/
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/ming32sh.cmd")
|
||||
message("Installing ming32sh.cmd")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${PATCH_DIR}/ming32sh.cmd ${DOWNLOAD_DIR}/mingw/mingw32/ming32sh.cmd
|
||||
)
|
||||
endif()
|
||||
|
||||
message("Checking for perl")
|
||||
# download perl for libvpx
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-32bit-portable.zip")
|
||||
message("Downloading perl")
|
||||
file(DOWNLOAD "http://strawberryperl.com/download/5.22.1.3/strawberry-perl-5.22.1.3-32bit-portable.zip" "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-32bit-portable.zip")
|
||||
endif()
|
||||
|
||||
# make perl root directory
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/perl32")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${DOWNLOAD_DIR}/perl32
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# extract perl
|
||||
if((NOT EXISTS "${DOWNLOAD_DIR}/perl32/portable.perl") AND (EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-32bit-portable.zip"))
|
||||
message("Extracting perl")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-32bit-portable.zip
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/perl32
|
||||
)
|
||||
endif()
|
||||
|
||||
# get yasm for vpx
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/yasm.exe")
|
||||
message("Downloading yasm")
|
||||
file(DOWNLOAD "http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win32.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/yasm.exe")
|
||||
endif()
|
||||
|
||||
message("checking i686-w64-mingw32-strings")
|
||||
# copy strings.exe to i686-w64-mingw32-strings for x264
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-strings.exe")
|
||||
message("fixing i686-w64-mingw32-strings.exe")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw32/bin/strings.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-strings.exe"
|
||||
)
|
||||
endif()
|
||||
|
||||
message("checking i686-w64-mingw32-ar.exe")
|
||||
# copy ar.exe to i686-w64-mingw32-ar.exe for x264
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ar.exe")
|
||||
message("fixing i686-w64-mingw32-ar.exe")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw32/bin/ar.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ar.exe"
|
||||
)
|
||||
endif()
|
||||
|
||||
message("checking i686-w64-mingw32-strip.exe")
|
||||
# copy strip.exe to i686-w64-mingw32-strip.exe for x264
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-strip.exe")
|
||||
message("fixing i686-w64-mingw32-strip.exe")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw32/bin/strip.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-strip.exe"
|
||||
)
|
||||
endif()
|
||||
|
||||
message("checking i686-w64-mingw32-ranlib.exe")
|
||||
# copy ranlib.exe to i686-w64-mingw32-ranlib.exe for x264
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ranlib.exe")
|
||||
message("fixing i686-w64-mingw32-ranlib.exe")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DOWNLOAD_DIR}/mingw/mingw32/bin/ranlib.exe" "${DOWNLOAD_DIR}/mingw/mingw32/bin/i686-w64-mingw32-ranlib.exe"
|
||||
)
|
||||
endif()
|
@@ -19,7 +19,7 @@
|
||||
####################################################################################################################
|
||||
# Mingw64 Builds
|
||||
####################################################################################################################
|
||||
# This installs mingw64+msys to compile ffmpeg/iconv/libsndfile/lapack/fftw3
|
||||
# This installs mingw64+msys to compile ffmpeg/iconv/libsndfile/fftw3
|
||||
####################################################################################################################
|
||||
|
||||
message("LIBDIR = ${LIBDIR}")
|
||||
@@ -128,6 +128,14 @@ if((EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/mingw-get.exe") AND (NOT EXISTS "$
|
||||
)
|
||||
endif()
|
||||
|
||||
if((EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/bin/mingw-get.exe") AND (NOT EXISTS "${DOWNLOAD_DIR}/mingw/mingw64/msys/1.0/bin/m4.exe"))
|
||||
message("Installing m4")
|
||||
execute_process(
|
||||
COMMAND ${DOWNLOAD_DIR}/mingw/mingw64/bin/mingw-get install msys msys-m4
|
||||
WORKING_DIRECTORY ${DOWNLOAD_DIR}/mingw/mingw64/bin/
|
||||
)
|
||||
endif()
|
||||
|
||||
message("Checking for CoreUtils")
|
||||
# download old core_utils for pr.exe (ffmpeg needs it to build)
|
||||
if(NOT EXISTS "${DOWNLOAD_DIR}/coreutils-5.97-MSYS-1.0.11-snapshot.tar.bz2")
|
||||
|
@@ -1,4 +1,4 @@
|
||||
%targets = (
|
||||
my %targets = (
|
||||
|
||||
"blender-linux-x86" => {
|
||||
inherit_from => [ "linux-x86" ],
|
||||
|
@@ -50,6 +50,13 @@ ExternalProject_Add(external_tbb
|
||||
if(WIN32)
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
ExternalProject_Add_Step(external_tbb after_install
|
||||
# findtbb.cmake in some deps *NEEDS* to find tbb_debug.lib even if they are not going to use it
|
||||
# to make that test pass, we place a copy with the right name in the lib folder.
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.lib ${HARVEST_TARGET}/tbb/lib/tbb_debug.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc_debug.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.dll ${HARVEST_TARGET}/tbb/lib/tbb_debug.dll
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.dll ${HARVEST_TARGET}/tbb/lib/tbbmalloc_debug.dll
|
||||
# Normal collection of build artifacts
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.lib ${HARVEST_TARGET}/tbb/lib/tbb.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbb.dll ${HARVEST_TARGET}/tbb/lib/tbb.dll
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/tbb/lib/tbbmalloc.lib ${HARVEST_TARGET}/tbb/lib/tbbmalloc.lib
|
||||
|
@@ -27,6 +27,9 @@ set(USD_EXTRA_ARGS
|
||||
-DTBB_INCLUDE_DIRS=${LIBDIR}/tbb/include
|
||||
-DTBB_LIBRARIES=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${LIBEXT}
|
||||
-DTbb_TBB_LIBRARY=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${LIBEXT}
|
||||
# USD wants the tbb debug lib set even when you are doing a release build
|
||||
# Otherwise it will error out during the cmake configure phase.
|
||||
-DTBB_LIBRARIES_DEBUG=${LIBDIR}/tbb/lib/${LIBPREFIX}${TBB_LIBRARY}${LIBEXT}
|
||||
|
||||
# This is a preventative measure that avoids possible conflicts when add-ons
|
||||
# try to load another USD library into the same process space.
|
||||
@@ -78,14 +81,14 @@ if(WIN32)
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
ExternalProject_Add_Step(external_usd after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/usd/ ${HARVEST_TARGET}/usd
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Release/libusd_m.lib ${HARVEST_TARGET}/usd/lib/libusd_m.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Release/usd_m.lib ${HARVEST_TARGET}/usd/lib/libusd_m.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
if(BUILD_MODE STREQUAL Debug)
|
||||
ExternalProject_Add_Step(external_usd after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/usd/lib ${HARVEST_TARGET}/usd/lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Debug/libusd_m_d.lib ${HARVEST_TARGET}/usd/lib/libusd_m_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/usd/src/external_usd-build/pxr/Debug/usd_m_d.lib ${HARVEST_TARGET}/usd/lib/libusd_m_d.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
@@ -78,10 +78,6 @@ set(FREEGLUT_VERSION 3.0.0)
|
||||
set(FREEGLUT_URI http://pilotfiber.dl.sourceforge.net/project/freeglut/freeglut/${FREEGLUT_VERSION}/freeglut-${FREEGLUT_VERSION}.tar.gz)
|
||||
set(FREEGLUT_HASH 90c3ca4dd9d51cf32276bc5344ec9754)
|
||||
|
||||
set(HDF5_VERSION 1.8.17)
|
||||
set(HDF5_URI https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.8/hdf5-${HDF5_VERSION}/src/hdf5-${HDF5_VERSION}.tar.gz)
|
||||
set(HDF5_HASH 7d572f8f3b798a628b8245af0391a0ca)
|
||||
|
||||
set(ALEMBIC_VERSION 1.7.12)
|
||||
set(ALEMBIC_URI https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.tar.gz)
|
||||
set(ALEMBIC_MD5 e2b3777f23c5c09481a008cc6f0f8a40)
|
||||
@@ -139,11 +135,11 @@ set(OSL_VERSION 1.10.10)
|
||||
set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz)
|
||||
set(OSL_HASH 00dec08a93c8084e53848b9ad047889f)
|
||||
|
||||
set(PYTHON_VERSION 3.7.4)
|
||||
set(PYTHON_VERSION 3.7.7)
|
||||
set(PYTHON_SHORT_VERSION 3.7)
|
||||
set(PYTHON_SHORT_VERSION_NO_DOTS 37)
|
||||
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
|
||||
set(PYTHON_HASH d33e4aae66097051c2eca45ee3604803)
|
||||
set(PYTHON_HASH 172c650156f7bea68ce31b2fd01fa766)
|
||||
|
||||
set(TBB_VERSION 2019_U9)
|
||||
set(TBB_URI https://github.com/oneapi-src/oneTBB/archive/${TBB_VERSION}.tar.gz)
|
||||
@@ -153,16 +149,16 @@ set(OPENVDB_VERSION 7.0.0)
|
||||
set(OPENVDB_URI https://github.com/dreamworksanimation/openvdb/archive/v${OPENVDB_VERSION}.tar.gz)
|
||||
set(OPENVDB_HASH fd6c4f168282f7e0e494d290cd531fa8)
|
||||
|
||||
set(IDNA_VERSION 2.8)
|
||||
set(IDNA_VERSION 2.9)
|
||||
set(CHARDET_VERSION 3.0.4)
|
||||
set(URLLIB3_VERSION 1.25.3)
|
||||
set(CERTIFI_VERSION 2019.6.16)
|
||||
set(REQUESTS_VERSION 2.22.0)
|
||||
set(URLLIB3_VERSION 1.25.9)
|
||||
set(CERTIFI_VERSION 2020.4.5.2)
|
||||
set(REQUESTS_VERSION 2.23.0)
|
||||
|
||||
set(NUMPY_VERSION v1.17.0)
|
||||
set(NUMPY_VERSION 1.17.5)
|
||||
set(NUMPY_SHORT_VERSION 1.17)
|
||||
set(NUMPY_URI https://files.pythonhosted.org/packages/da/32/1b8f2bb5fb50e4db68543eb85ce37b9fa6660cd05b58bddfafafa7ed62da/numpy-1.17.0.zip)
|
||||
set(NUMPY_HASH aed49b31bcb44ec73b8155be78566135)
|
||||
set(NUMPY_URI https://github.com/numpy/numpy/releases/download/v${NUMPY_VERSION}/numpy-${NUMPY_VERSION}.zip)
|
||||
set(NUMPY_HASH 763a5646fa6eef7a22f4895bca0524f2)
|
||||
|
||||
set(LAME_VERSION 3.100)
|
||||
set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.100/lame-${LAME_VERSION}.tar.gz)
|
||||
@@ -192,8 +188,8 @@ set(OPUS_VERSION 1.3.1)
|
||||
set(OPUS_URI https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz)
|
||||
set(OPUS_HASH 65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d)
|
||||
|
||||
set(X264_URI https://code.videolan.org/videolan/x264/-/archive/master/x264-33f9e1474613f59392be5ab6a7e7abf60fa63622.tar.gz)
|
||||
set(X264_HASH 300dfb5b6c35722516f168868ce9419252a9e9eb77a05d82c9cede925b691bd6)
|
||||
set(X264_URI https://code.videolan.org/videolan/x264/-/archive/33f9e1474613f59392be5ab6a7e7abf60fa63622/x264-33f9e1474613f59392be5ab6a7e7abf60fa63622.tar.gz)
|
||||
set(X264_HASH 5456450ee1ae02cd2328be3157367a232a0ab73315e8c8f80dab80469524f525)
|
||||
|
||||
set(XVIDCORE_VERSION 1.3.7)
|
||||
set(XVIDCORE_URI https://downloads.xvid.com/downloads/xvidcore-${XVIDCORE_VERSION}.tar.gz)
|
||||
@@ -216,10 +212,6 @@ set(ICONV_VERSION 1.16)
|
||||
set(ICONV_URI http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz)
|
||||
set(ICONV_HASH 7d2a800b952942bb2880efb00cfd524c)
|
||||
|
||||
set(LAPACK_VERSION 3.6.0)
|
||||
set(LAPACK_URI http://www.netlib.org/lapack/lapack-${LAPACK_VERSION}.tgz)
|
||||
set(LAPACK_HASH f2f6c67134e851fe189bb3ca1fbb5101)
|
||||
|
||||
set(SNDFILE_VERSION 1.0.28)
|
||||
set(SNDFILE_URI http://www.mega-nerd.com/libsndfile/files/libsndfile-${SNDFILE_VERSION}.tar.gz)
|
||||
set(SNDFILE_HASH 646b5f98ce89ac60cdb060fcd398247c)
|
||||
@@ -240,13 +232,13 @@ set(SPNAV_VERSION 0.2.3)
|
||||
set(SPNAV_URI http://downloads.sourceforge.net/project/spacenav/spacenav%20library%20%28SDK%29/libspnav%20${SPNAV_VERSION}/libspnav-${SPNAV_VERSION}.tar.gz)
|
||||
set(SPNAV_HASH 44d840540d53326d4a119c0f1aa7bf0a)
|
||||
|
||||
set(JEMALLOC_VERSION 5.0.1)
|
||||
set(JEMALLOC_VERSION 5.2.1)
|
||||
set(JEMALLOC_URI https://github.com/jemalloc/jemalloc/releases/download/${JEMALLOC_VERSION}/jemalloc-${JEMALLOC_VERSION}.tar.bz2)
|
||||
set(JEMALLOC_HASH 507f7b6b882d868730d644510491d18f)
|
||||
set(JEMALLOC_HASH 3d41fbf006e6ebffd489bdb304d009ae)
|
||||
|
||||
set(XML2_VERSION 2.9.4)
|
||||
set(XML2_VERSION 2.9.10)
|
||||
set(XML2_URI http://xmlsoft.org/sources/libxml2-${XML2_VERSION}.tar.gz)
|
||||
set(XML2_HASH ae249165c173b1ff386ee8ad676815f5)
|
||||
set(XML2_HASH 10942a1dc23137a8aa07f0639cbfece5)
|
||||
|
||||
set(TINYXML_VERSION 2_6_2)
|
||||
set(TINYXML_VERSION_DOTS 2.6.2)
|
||||
@@ -273,23 +265,23 @@ set(FLEXBISON_HASH d87a3938194520d904013abef3df10ce)
|
||||
|
||||
# NOTE: bzip.org domain does no longer belong to BZip 2 project, so we download
|
||||
# sources from Debian packaging.
|
||||
set(BZIP2_VERSION 1.0.6)
|
||||
set(BZIP2_URI http://http.debian.net/debian/pool/main/b/bzip2/bzip2_${BZIP2_VERSION}.orig.tar.bz2)
|
||||
set(BZIP2_HASH d70a9ccd8bdf47e302d96c69fecd54925f45d9c7b966bb4ef5f56b770960afa7)
|
||||
set(BZIP2_VERSION 1.0.8)
|
||||
set(BZIP2_URI http://http.debian.net/debian/pool/main/b/bzip2/bzip2_${BZIP2_VERSION}.orig.tar.gz)
|
||||
set(BZIP2_HASH ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269)
|
||||
|
||||
set(FFI_VERSION 3.2.1)
|
||||
set(FFI_VERSION 3.3)
|
||||
set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz)
|
||||
set(FFI_HASH d06ebb8e1d9a22d19e38d63fdb83954253f39bedc5d46232a05645685722ca37)
|
||||
set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056)
|
||||
|
||||
set(LZMA_VERSION 5.2.4)
|
||||
set(LZMA_VERSION 5.2.5)
|
||||
set(LZMA_URI https://tukaani.org/xz/xz-${LZMA_VERSION}.tar.bz2)
|
||||
set(LZMA_HASH 3313fd2a95f43d88e44264e6b015e7d03053e681860b0d5d3f9baca79c57b7bf)
|
||||
set(LZMA_HASH 5117f930900b341493827d63aa910ff5e011e0b994197c3b71c08a20228a42df)
|
||||
|
||||
set(SSL_VERSION 1.1.0i)
|
||||
set(SSL_VERSION 1.1.1g)
|
||||
set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
|
||||
set(SSL_HASH ebbfc844a8c8cc0ea5dc10b86c9ce97f401837f3fa08c17b2cdadc118253cf99)
|
||||
set(SSL_HASH ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46)
|
||||
|
||||
set(SQLITE_VERSION 3.24.0)
|
||||
set(SQLITE_VERSION 3.31.1)
|
||||
set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip)
|
||||
set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7)
|
||||
|
||||
@@ -297,13 +289,13 @@ set(EMBREE_VERSION 3.10.0)
|
||||
set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip)
|
||||
set(EMBREE_HASH 4bbe29e7eaa46417efc75fc5f1e8eb87)
|
||||
|
||||
set(USD_VERSION 19.11)
|
||||
set(USD_VERSION 20.05)
|
||||
set(USD_URI https://github.com/PixarAnimationStudios/USD/archive/v${USD_VERSION}.tar.gz)
|
||||
set(USD_HASH 79ff176167b3fe85f4953abd6cc5e0cc)
|
||||
set(USD_HASH 6d679e739e7f65725d9c029e37dda9fc)
|
||||
|
||||
set(OIDN_VERSION 1.0.0)
|
||||
set(OIDN_URI https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.zip)
|
||||
set(OIDN_HASH 19fe67b0164e8f020ac8a4f520defe60)
|
||||
set(OIDN_VERSION 1.2.1)
|
||||
set(OIDN_URI https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.tar.gz)
|
||||
set(OIDN_HASH cbebc1a25eb6de62af3a59e943063608)
|
||||
|
||||
set(LIBGLU_VERSION 9.0.1)
|
||||
set(LIBGLU_URI ftp://ftp.freedesktop.org/pub/mesa/glu/glu-${LIBGLU_VERSION}.tar.xz)
|
||||
@@ -316,3 +308,6 @@ set(MESA_HASH d60828056d77bfdbae0970f9b15fb1be)
|
||||
set(XR_OPENXR_SDK_VERSION 1.0.8)
|
||||
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)
|
||||
set(XR_OPENXR_SDK_HASH c6de63d2e0f9029aa58dfa97cad8ce07)
|
||||
set(ISPC_VERSION v1.13.0)
|
||||
set(ISPC_URI https://github.com/ispc/ispc/archive/${ISPC_VERSION}.tar.gz)
|
||||
set(ISPC_HASH 4bf5e8d0020c4b9980faa702c1a6f25f)
|
||||
|
@@ -376,7 +376,7 @@ USE_CXX11=true
|
||||
|
||||
CLANG_FORMAT_VERSION_MIN="6.0"
|
||||
|
||||
PYTHON_VERSION="3.7.4"
|
||||
PYTHON_VERSION="3.7.7"
|
||||
PYTHON_VERSION_MIN="3.7"
|
||||
PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_MIN
|
||||
PYTHON_FORCE_BUILD=false
|
||||
@@ -459,7 +459,7 @@ ALEMBIC_FORCE_BUILD=false
|
||||
ALEMBIC_FORCE_REBUILD=false
|
||||
ALEMBIC_SKIP=false
|
||||
|
||||
USD_VERSION="19.11"
|
||||
USD_VERSION="20.05"
|
||||
USD_FORCE_BUILD=false
|
||||
USD_FORCE_REBUILD=false
|
||||
USD_SKIP=false
|
||||
@@ -1574,7 +1574,7 @@ compile_TBB() {
|
||||
if [ ! -d $_inst ]; then
|
||||
INFO "Building TBB-$TBB_VERSION$TBB_VERSION_UPDATE"
|
||||
_is_building=true
|
||||
|
||||
|
||||
# Rebuild dependencies as well!
|
||||
_update_deps_tbb
|
||||
|
||||
@@ -1691,7 +1691,7 @@ compile_OCIO() {
|
||||
if [ ! -d $_inst ]; then
|
||||
INFO "Building OpenColorIO-$OCIO_VERSION"
|
||||
_is_building=true
|
||||
|
||||
|
||||
# Rebuild dependencies as well!
|
||||
_update_deps_ocio
|
||||
|
||||
@@ -3428,7 +3428,7 @@ compile_XR_OpenXR_SDK() {
|
||||
# Install on DEB-like
|
||||
|
||||
get_package_version_DEB() {
|
||||
dpkg-query -W -f '${Version}' $1 | sed -r 's/([0-9]+:)?(([0-9]+\.?){$2}([0-9]+)).*/\2/'
|
||||
dpkg-query -W -f '${Version}' $1 | sed -r 's/([0-9]+:)?(([0-9]+\.?)+([0-9]+)).*/\2/'
|
||||
}
|
||||
|
||||
check_package_DEB() {
|
||||
@@ -3631,7 +3631,7 @@ install_DEB() {
|
||||
# Check cmake/glew versions and disable features for older distros.
|
||||
# This is so Blender can at least compile.
|
||||
PRINT ""
|
||||
_cmake=`get_package_version_DEB cmake 3`
|
||||
_cmake=`get_package_version_DEB cmake`
|
||||
version_ge $_cmake "2.8.10"
|
||||
if [ $? -eq 1 ]; then
|
||||
version_ge $_cmake "2.8.8"
|
||||
@@ -3646,7 +3646,7 @@ install_DEB() {
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
_glew=`get_package_version_DEB libglew-dev 3`
|
||||
_glew=`get_package_version_DEB libglew-dev`
|
||||
if [ -z $_glew ]; then
|
||||
# Stupid virtual package in Ubuntu 12.04 doesn't show version number...
|
||||
_glew=`apt-cache showpkg libglew-dev|tail -n1|awk '{print $2}'|sed 's/-.*//'`
|
||||
@@ -3678,8 +3678,7 @@ install_DEB() {
|
||||
check_package_version_ge_DEB python3-dev $PYTHON_VERSION_MIN
|
||||
if [ $? -eq 0 ]; then
|
||||
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_DEB python3-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
PRINT $(echo `get_package_version_DEB python3-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
|
||||
|
||||
install_packages_DEB python3-dev
|
||||
clean_Python
|
||||
PRINT ""
|
||||
@@ -3893,7 +3892,6 @@ install_DEB() {
|
||||
INFO "Forced Alembic building, as requested..."
|
||||
compile_ALEMBIC
|
||||
else
|
||||
# No package currently, only HDF5!
|
||||
compile_ALEMBIC
|
||||
fi
|
||||
|
||||
@@ -4302,8 +4300,7 @@ install_RPM() {
|
||||
else
|
||||
check_package_version_ge_RPM python3-devel $PYTHON_VERSION_MIN
|
||||
if [ $? -eq 0 ]; then
|
||||
get_package_version_RPM python3-devel
|
||||
PYTHON_VERSION_INSTALLED=`echo $? | sed -r 's/([0-9]+:)?(([0-9]+\.?)?([0-9]+)).*/\2/'`
|
||||
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_RPM python3-devel` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
|
||||
install_packages_RPM python3-devel
|
||||
clean_Python
|
||||
@@ -4828,8 +4825,7 @@ install_ARCH() {
|
||||
else
|
||||
check_package_version_ge_ARCH python $PYTHON_VERSION_MIN
|
||||
if [ $? -eq 0 ]; then
|
||||
get_package_version_ARCH python
|
||||
PYTHON_VERSION_INSTALLED=`echo $? | sed -r 's/([0-9]+:)?(([0-9]+\.?)?([0-9]+)).*/\2/'`
|
||||
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_ARCH python` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
|
||||
install_packages_ARCH python
|
||||
clean_Python
|
||||
|
@@ -1,20 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(hidapi)
|
||||
|
||||
set(SRC_FILES
|
||||
windows/hid.c
|
||||
)
|
||||
|
||||
set(HEADER_FILES
|
||||
hidapi/hidapi.h
|
||||
)
|
||||
include_directories(hidapi)
|
||||
add_definitions(-DHID_API_STATIC)
|
||||
add_library(hidapi STATIC ${SRC_FILES} ${HEADER_FILES})
|
||||
|
||||
install(TARGETS hidapi DESTINATION lib)
|
||||
|
||||
INSTALL(FILES hidapi/hidapi.h
|
||||
DESTINATION "include"
|
||||
)
|
||||
|
14
build_files/build_environment/patches/embree.diff
Normal file
14
build_files/build_environment/patches/embree.diff
Normal file
@@ -0,0 +1,14 @@
|
||||
diff -Naur orig/common/sys/platform.h external_embree/common/sys/platform.h
|
||||
--- orig/common/sys/platform.h 2020-05-13 23:08:53 -0600
|
||||
+++ external_embree/common/sys/platform.h 2020-06-13 17:40:26 -0600
|
||||
@@ -84,8 +84,8 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __WIN32__
|
||||
-#define dll_export __declspec(dllexport)
|
||||
-#define dll_import __declspec(dllimport)
|
||||
+#define dll_export
|
||||
+#define dll_import
|
||||
#else
|
||||
#define dll_export __attribute__ ((visibility ("default")))
|
||||
#define dll_import
|
@@ -1,15 +0,0 @@
|
||||
--- hidapi/hidapi.h 2011-10-25 20:58:16 -0600
|
||||
+++ hidapi/hidapi.h 2016-11-01 12:05:58 -0600
|
||||
@@ -30,7 +30,11 @@
|
||||
#include <wchar.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
- #define HID_API_EXPORT __declspec(dllexport)
|
||||
+ #ifdef HID_API_STATIC
|
||||
+ #define HID_API_EXPORT
|
||||
+ #else
|
||||
+ #define HID_API_EXPORT __declspec(dllexport)
|
||||
+ #endif
|
||||
#define HID_API_CALL
|
||||
#else
|
||||
#define HID_API_EXPORT /**< API export macro */
|
36
build_files/build_environment/patches/ispc.diff
Normal file
36
build_files/build_environment/patches/ispc.diff
Normal file
@@ -0,0 +1,36 @@
|
||||
diff -Naur external_ispc/CMakeLists.txt external_ispc_fixed/CMakeLists.txt
|
||||
--- external_ispc/CMakeLists.txt 2020-04-23 17:29:06 -0600
|
||||
+++ external_ispc_fixed/CMakeLists.txt 2020-05-05 09:01:09 -0600
|
||||
@@ -389,7 +389,7 @@
|
||||
|
||||
# Link against Clang libraries
|
||||
foreach(clangLib ${CLANG_LIBRARY_LIST})
|
||||
- find_library(${clangLib}Path NAMES ${clangLib} HINTS ${LLVM_LIBRARY_DIRS})
|
||||
+ find_library(${clangLib}Path NAMES ${clangLib} HINTS ${LLVM_LIBRARY_DIRS} ${CLANG_LIBRARY_DIR})
|
||||
list(APPEND CLANG_LIBRARY_FULL_PATH_LIST ${${clangLib}Path})
|
||||
endforeach()
|
||||
target_link_libraries(${PROJECT_NAME} ${CLANG_LIBRARY_FULL_PATH_LIST})
|
||||
diff -Naur orig/CMakeLists.txt external_ispc/CMakeLists.txt
|
||||
--- orig/CMakeLists.txt 2020-05-05 09:19:11 -0600
|
||||
+++ external_ispc/CMakeLists.txt 2020-05-05 09:26:44 -0600
|
||||
@@ -333,7 +333,7 @@
|
||||
|
||||
# Include directories
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
- ${LLVM_INCLUDE_DIRS}
|
||||
+ ${LLVM_INCLUDE_DIRS} ${CLANG_INCLUDE_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR})
|
||||
# Compile options
|
||||
diff -Naur orig/cmake/GenerateBuiltins.cmake.txt external_ispc/cmake/GenerateBuiltins.cmake.txt
|
||||
+++ orig/cmake/GenerateBuiltins.cmake 2020-05-25 13:32:40.830803821 +0200
|
||||
+++ external_ispc/cmake/GenerateBuiltins.cmake 2020-05-25 13:32:40.830803821 +0200
|
||||
@@ -97,6 +97,8 @@
|
||||
|
||||
if ("${bit}" STREQUAL "32" AND ${arch} STREQUAL "x86")
|
||||
set(target_arch "i386")
|
||||
+ # Blender: disable 32bit due to build issues on Linux and being unnecessary.
|
||||
+ set(SKIP ON)
|
||||
elseif ("${bit}" STREQUAL "64" AND ${arch} STREQUAL "x86")
|
||||
set(target_arch "x86_64")
|
||||
elseif ("${bit}" STREQUAL "32" AND ${arch} STREQUAL "arm")
|
@@ -1,120 +0,0 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 70ec895..e616b63 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -178,7 +178,9 @@ set_property(TARGET ${PROJECT_NAME} PROPERTY SOVERSION "0")
|
||||
## Open Image Denoise examples
|
||||
## ----------------------------------------------------------------------------
|
||||
|
||||
-add_subdirectory(examples)
|
||||
+if(WITH_EXAMPLE)
|
||||
+ add_subdirectory(examples)
|
||||
+endif()
|
||||
|
||||
## ----------------------------------------------------------------------------
|
||||
## Open Image Denoise install and packaging
|
||||
Submodule mkl-dnn contains modified content
|
||||
diff --git a/mkl-dnn/cmake/TBB.cmake b/mkl-dnn/cmake/TBB.cmake
|
||||
index 0711e699..c14210b6 100644
|
||||
--- a/mkl-dnn/cmake/TBB.cmake
|
||||
+++ b/mkl-dnn/cmake/TBB.cmake
|
||||
@@ -138,13 +138,13 @@ else()
|
||||
set(TBB_LIBRARY_MALLOC TBB_LIBRARY_MALLOC-NOTFOUND)
|
||||
if(APPLE)
|
||||
find_path(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH)
|
||||
- find_library(TBB_LIBRARY tbb PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH)
|
||||
- find_library(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH)
|
||||
+ find_library(TBB_LIBRARY tbb_static PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH)
|
||||
+ find_library(TBB_LIBRARY_MALLOC tbbmalloc_static PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH)
|
||||
else()
|
||||
find_path(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH)
|
||||
set(TBB_HINTS HINTS ${TBB_ROOT}/lib/intel64/gcc4.4 ${TBB_ROOT}/lib ${TBB_ROOT}/lib64 PATHS /usr/libx86_64-linux-gnu/)
|
||||
- find_library(TBB_LIBRARY tbb ${TBB_HINTS})
|
||||
- find_library(TBB_LIBRARY_MALLOC tbbmalloc ${TBB_HINTS})
|
||||
+ find_library(TBB_LIBRARY tbb_static ${TBB_HINTS})
|
||||
+ find_library(TBB_LIBRARY_MALLOC tbbmalloc_static ${TBB_HINTS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
diff '--ignore-matching-lines=:' -ur '--exclude=*.svn*' -u -r
|
||||
--- a/cmake/install.cmake 2019-08-12 18:02:20.794402575 +0200
|
||||
+++ b/cmake/install.cmake 2019-08-12 18:06:07.470045703 +0200
|
||||
@@ -18,6 +18,13 @@
|
||||
## Install library
|
||||
## ----------------------------------------------------------------------------
|
||||
|
||||
+if(UNIX)
|
||||
+install(FILES
|
||||
+ ${CMAKE_BINARY_DIR}/libOpenImageDenoise.a
|
||||
+ ${CMAKE_BINARY_DIR}/libmkldnn.a
|
||||
+ ${CMAKE_BINARY_DIR}/libcommon.a
|
||||
+ DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
+else()
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
EXPORT
|
||||
${PROJECT_NAME}_Export
|
||||
@@ -38,6 +45,7 @@
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel
|
||||
)
|
||||
endif()
|
||||
+endif()
|
||||
|
||||
## ----------------------------------------------------------------------------
|
||||
## Install headers
|
||||
@@ -78,6 +86,7 @@
|
||||
## Install CMake configuration files
|
||||
## ----------------------------------------------------------------------------
|
||||
|
||||
+if(NOT UNIX)
|
||||
install(EXPORT ${PROJECT_NAME}_Export
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
#NAMESPACE ${PROJECT_NAME}::
|
||||
@@ -92,3 +101,4 @@
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
COMPONENT devel
|
||||
)
|
||||
+endif()
|
||||
diff '--ignore-matching-lines=:' -ur '--exclude=*.svn*' -u -r
|
||||
--- a/CMakeLists.txt 2019-08-12 14:22:00.974078598 +0200
|
||||
+++ b/CMakeLists.txt 2019-08-12 18:05:05.949057375 +0200
|
||||
@@ -14,7 +14,11 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
-cmake_minimum_required(VERSION 3.1)
|
||||
+if(UNIX)
|
||||
+ cmake_minimum_required(VERSION 3.1)
|
||||
+else()
|
||||
+ cmake_minimum_required(VERSION 3.13)
|
||||
+endif()
|
||||
|
||||
set(OIDN_VERSION_MAJOR 1)
|
||||
set(OIDN_VERSION_MINOR 0)
|
||||
@@ -32,13 +36,8 @@
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
||||
|
||||
# Build as shared or static library
|
||||
-if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
|
||||
- option(OIDN_STATIC_LIB "Build Open Image Denoise as a static library.")
|
||||
- mark_as_advanced(CLEAR OIDN_STATIC_LIB)
|
||||
-else()
|
||||
- set(OIDN_STATIC_LIB OFF CACHE BOOL "Build Open Image Denoise as a static library." FORCE)
|
||||
- mark_as_advanced(OIDN_STATIC_LIB)
|
||||
-endif()
|
||||
+option(OIDN_STATIC_LIB "Build Open Image Denoise as a static library.")
|
||||
+mark_as_advanced(CLEAR OIDN_STATIC_LIB)
|
||||
if(OIDN_STATIC_LIB)
|
||||
set(OIDN_LIB_TYPE STATIC)
|
||||
else()
|
||||
diff -Naur orig/core/api.cpp external_openimagedenoise/core/api.cpp
|
||||
--- orig/core/api.cpp 2019-07-19 08:37:04 -0600
|
||||
+++ external_openimagedenoise/core/api.cpp 2020-01-21 15:10:56 -0700
|
||||
@@ -15,7 +15,7 @@
|
||||
// ======================================================================== //
|
||||
|
||||
#ifdef _WIN32
|
||||
-# define OIDN_API extern "C" __declspec(dllexport)
|
||||
+# define OIDN_API extern "C"
|
||||
#else
|
||||
# define OIDN_API extern "C" __attribute__ ((visibility ("default")))
|
||||
#endif
|
@@ -1,14 +1,3 @@
|
||||
diff -x .git -ur usd.orig/cmake/defaults/Options.cmake external_usd/cmake/defaults/Options.cmake
|
||||
--- usd.orig/cmake/defaults/Options.cmake 2019-10-24 22:39:53.000000000 +0200
|
||||
+++ external_usd/cmake/defaults/Options.cmake 2019-11-28 13:00:33.197957712 +0100
|
||||
@@ -25,6 +25,7 @@
|
||||
option(PXR_VALIDATE_GENERATED_CODE "Validate script generated code" OFF)
|
||||
option(PXR_HEADLESS_TEST_MODE "Disallow GUI based tests, useful for running under headless CI systems." OFF)
|
||||
option(PXR_BUILD_TESTS "Build tests" ON)
|
||||
+option(PXR_BUILD_USD_TOOLS "Build commandline tools" ON)
|
||||
option(PXR_BUILD_IMAGING "Build imaging components" ON)
|
||||
option(PXR_BUILD_EMBREE_PLUGIN "Build embree imaging plugin" OFF)
|
||||
option(PXR_BUILD_OPENIMAGEIO_PLUGIN "Build OpenImageIO plugin" OFF)
|
||||
diff -x .git -ur usd.orig/cmake/defaults/Packages.cmake external_usd/cmake/defaults/Packages.cmake
|
||||
--- usd.orig/cmake/defaults/Packages.cmake 2019-10-24 22:39:53.000000000 +0200
|
||||
+++ external_usd/cmake/defaults/Packages.cmake 2019-11-28 13:00:33.185957483 +0100
|
||||
@@ -21,11 +10,11 @@ diff -x .git -ur usd.orig/cmake/defaults/Packages.cmake external_usd/cmake/defau
|
||||
add_definitions(${TBB_DEFINITIONS})
|
||||
|
||||
# --math
|
||||
diff -x .git -ur usd.orig/pxr/base/lib/plug/initConfig.cpp external_usd/pxr/base/lib/plug/initConfig.cpp
|
||||
--- usd.orig/pxr/base/lib/plug/initConfig.cpp 2019-10-24 22:39:53.000000000 +0200
|
||||
+++ external_usd/pxr/base/lib/plug/initConfig.cpp 2019-12-11 11:00:37.643323127 +0100
|
||||
@@ -69,8 +69,38 @@
|
||||
|
||||
diff -x .git -ur usd.orig/pxr/base/plug/initConfig.cpp external_usd/pxr/base/plug/initConfig.cpp
|
||||
--- usd.orig/pxr/base/plug/initConfig.cpp.orig 2020-06-12 17:20:07.478199779 +0200
|
||||
+++ external_usd/pxr/base/plug/initConfig.cpp 2020-06-12 17:25:28.648588552 +0200
|
||||
@@ -69,10 +69,40 @@
|
||||
|
||||
ARCH_CONSTRUCTOR(Plug_InitConfig, 2, void)
|
||||
{
|
||||
+ /* The contents of this constructor have been moved to usd_initialise_plugin_path(...) */
|
||||
@@ -50,7 +39,9 @@ diff -x .git -ur usd.orig/pxr/base/lib/plug/initConfig.cpp external_usd/pxr/base
|
||||
+usd_initialise_plugin_path(const char *datafiles_usd_path)
|
||||
+{
|
||||
std::vector<std::string> result;
|
||||
|
||||
|
||||
std::vector<std::string> debugMessages;
|
||||
|
||||
+ // Add Blender-specific paths. They MUST end in a slash, or symlinks will not be treated as directory.
|
||||
+ if (datafiles_usd_path != NULL && datafiles_usd_path[0] != '\0') {
|
||||
+ std::string datafiles_usd_path_str(datafiles_usd_path);
|
||||
@@ -60,14 +51,14 @@ diff -x .git -ur usd.orig/pxr/base/lib/plug/initConfig.cpp external_usd/pxr/base
|
||||
+ result.push_back(datafiles_usd_path_str);
|
||||
+ }
|
||||
+
|
||||
// Determine the absolute path to the Plug shared library.
|
||||
// Any relative paths specified in the plugin search path will be
|
||||
// anchored to this directory, to allow for relocatability.
|
||||
@@ -94,9 +124,24 @@
|
||||
_AppendPathList(&result, installLocation, sharedLibPath);
|
||||
// Determine the absolute path to the Plug shared library. Any relative
|
||||
// paths specified in the plugin search path will be anchored to this
|
||||
// directory, to allow for relocatability. Note that this can fail when pxr
|
||||
@@ -114,9 +144,24 @@
|
||||
_AppendPathList(&result, installLocation, binaryPath);
|
||||
#endif // PXR_INSTALL_LOCATION
|
||||
|
||||
- Plug_SetPaths(result);
|
||||
|
||||
- Plug_SetPaths(result, debugMessages);
|
||||
-}
|
||||
+ if (!TfGetenv("PXR_PATH_DEBUG").empty()) {
|
||||
+ printf("USD Plugin paths: (%zu in total):\n", result.size());
|
||||
@@ -75,10 +66,10 @@ diff -x .git -ur usd.orig/pxr/base/lib/plug/initConfig.cpp external_usd/pxr/base
|
||||
+ printf(" %s\n", path.c_str());
|
||||
+ }
|
||||
+ }
|
||||
|
||||
+ Plug_SetPaths(result);
|
||||
|
||||
+ Plug_SetPaths(result, debugMessages);
|
||||
}
|
||||
|
||||
|
||||
PXR_NAMESPACE_CLOSE_SCOPE
|
||||
+
|
||||
+/* Workaround to make it possible to pass a path at runtime to USD. */
|
||||
@@ -90,37 +81,6 @@ diff -x .git -ur usd.orig/pxr/base/lib/plug/initConfig.cpp external_usd/pxr/base
|
||||
+ PXR_NS::usd_initialise_plugin_path(datafiles_usd_path);
|
||||
+}
|
||||
+}
|
||||
diff -x .git -ur usd.orig/pxr/usd/CMakeLists.txt external_usd/pxr/usd/CMakeLists.txt
|
||||
--- usd.orig/pxr/usd/CMakeLists.txt 2019-10-24 22:39:53.000000000 +0200
|
||||
+++ external_usd/pxr/usd/CMakeLists.txt 2019-11-28 13:00:33.197957712 +0100
|
||||
@@ -1,6 +1,5 @@
|
||||
set(DIRS
|
||||
lib
|
||||
- bin
|
||||
plugin
|
||||
)
|
||||
|
||||
@@ -8,3 +7,8 @@
|
||||
add_subdirectory(${d})
|
||||
endforeach()
|
||||
|
||||
+if (PXR_BUILD_USD_TOOLS)
|
||||
+ add_subdirectory(bin)
|
||||
+else()
|
||||
+ message(STATUS "Skipping commandline tools because PXR_BUILD_USD_TOOLS=OFF")
|
||||
+endif()
|
||||
diff -Naur external_usd_orig/pxr/base/lib/tf/preprocessorUtils.h external_usd/pxr/base/lib/tf/preprocessorUtils.h
|
||||
--- external_usd_orig/pxr/base/lib/tf/preprocessorUtils.h 2019-10-24 14:39:53 -0600
|
||||
+++ external_usd/pxr/base/lib/tf/preprocessorUtils.h 2020-01-14 09:30:18 -0700
|
||||
@@ -189,7 +189,7 @@
|
||||
/// Exapnds to 1 if the argument is a tuple, and 0 otherwise.
|
||||
/// \ingroup group_tf_Preprocessor
|
||||
/// \hideinitializer
|
||||
-#if defined(ARCH_OS_WINDOWS)
|
||||
+#if defined(ARCH_COMPILER_MSVC)
|
||||
#define TF_PP_IS_TUPLE(sequence) \
|
||||
BOOST_VMD_IS_TUPLE(sequence)
|
||||
#else
|
||||
diff -Naur external_usd_base/cmake/macros/Public.cmake external_usd/cmake/macros/Public.cmake
|
||||
--- external_usd_base/cmake/macros/Public.cmake 2019-10-24 14:39:53 -0600
|
||||
+++ external_usd/cmake/macros/Public.cmake 2020-01-11 13:33:29 -0700
|
||||
|
34
build_files/buildbot-lts/README.md
Normal file
34
build_files/buildbot-lts/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
Buildbot-lts
|
||||
============
|
||||
|
||||
This folder contains configuration files and build scripts for making a release.
|
||||
It originated when we started to do LTS releases what happens once every two
|
||||
weeks. The idea is to automate the manual steps where possible and provide a
|
||||
pipeline process for the manual steps that still needs to happen.
|
||||
|
||||
By using the same software as builder.blender.org it would already put us in
|
||||
the right direction when we might want to make this part of builder.blender.org
|
||||
for now it is running on a VM in the blender institute as it contains user
|
||||
private keys and the process needs to be controlled security wise.
|
||||
|
||||
But of course the source and configurations are public available for anyone to
|
||||
check, develop and use.
|
||||
|
||||
Setting up build-bot
|
||||
--------------------
|
||||
|
||||
instructions from https://github.com/cjolowicz/docker-buildbot.
|
||||
|
||||
Create custom buildbot worker containing packages we need for building (git, wget).
|
||||
|
||||
cd docker
|
||||
docker build -t buildbot --no-cache .
|
||||
cd worker
|
||||
docker build -t buildbot-worker --no-cache .
|
||||
|
||||
docker network create net-buildbot
|
||||
|
||||
docker rm lts-buildbot && docker run --init --name lts-buildbot --network net-buildbot --publish=127.0.0.1:8010:8010 -t -i buildbot
|
||||
|
||||
docker rm lts-worker && docker run --init --name lts-worker --network net-buildbot --name lts-worker -e BUILDMASTER=lts-buildbot -e WORKERNAME=lts-worker -e WORKERPASS=secret -t -i buildbot-worker
|
||||
|
36
build_files/buildbot-lts/docker/Dockerfile
Normal file
36
build_files/buildbot-lts/docker/Dockerfile
Normal file
@@ -0,0 +1,36 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt update && apt upgrade -y
|
||||
RUN apt install -y \
|
||||
gosu \
|
||||
wget \
|
||||
openssh-client \
|
||||
build-essential \
|
||||
libffi-dev \
|
||||
libssl-dev \
|
||||
python3-dev \
|
||||
python3-pip
|
||||
|
||||
|
||||
ENV BUILDBOT_VERSION 2.5.0
|
||||
RUN pip3 --no-cache-dir install --upgrade pip && pip --no-cache-dir install \
|
||||
buildbot[bundle,tls]==$BUILDBOT_VERSION \
|
||||
buildbot-docker-swarm-worker
|
||||
|
||||
COPY buildbot.tac /var/lib/buildbot/
|
||||
COPY docker-entrypoint.sh /usr/local/bin/
|
||||
COPY master.cfg /etc/buildbot/
|
||||
COPY bin/create_checksum.sh /var/lib/buildbot/bin/
|
||||
COPY bin/upload_file.sh /var/lib/buildbot/bin/
|
||||
COPY .ssh/id_rsa /var/lib/buildbot/.ssh/
|
||||
|
||||
RUN adduser --home /var/lib/buildbot --disabled-password --gecos '' buildbot
|
||||
WORKDIR /var/lib/buildbot
|
||||
RUN ln -s /etc/buildbot/master.cfg
|
||||
|
||||
VOLUME /var/lib/buildbot
|
||||
EXPOSE 8010
|
||||
EXPOSE 9989
|
||||
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
CMD ["twistd", "--pidfile=", "--nodaemon", "--python=buildbot.tac"]
|
4
build_files/buildbot-lts/docker/bin/create_checksum.sh
Executable file
4
build_files/buildbot-lts/docker/bin/create_checksum.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
md5sum $1 > $2.md5
|
||||
sha256sum $1 > $2.sha256
|
7
build_files/buildbot-lts/docker/bin/upload_file.sh
Executable file
7
build_files/buildbot-lts/docker/bin/upload_file.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
if [ ! -f /var/lib/buildbot/.ssh/known_hosts ]
|
||||
then
|
||||
ssh-keyscan download.blender.org > /var/lib/buildbot/.ssh/known_hosts
|
||||
fi
|
||||
scp $1 jeroen@download.blender.org:$2
|
20
build_files/buildbot-lts/docker/buildbot.tac
Normal file
20
build_files/buildbot-lts/docker/buildbot.tac
Normal file
@@ -0,0 +1,20 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from twisted.application import service
|
||||
from twisted.python.log import FileLogObserver
|
||||
from twisted.python.log import ILogObserver
|
||||
|
||||
from buildbot.master import BuildMaster
|
||||
|
||||
basedir = os.environ.get("BUILDBOT_BASEDIR",
|
||||
os.path.abspath(os.path.dirname(__file__)))
|
||||
configfile = 'master.cfg'
|
||||
|
||||
# note: this line is matched against to check that this is a buildmaster
|
||||
# directory; do not edit it.
|
||||
application = service.Application('buildmaster')
|
||||
application.setComponent(ILogObserver, FileLogObserver(sys.stdout).emit)
|
||||
|
||||
m = BuildMaster(basedir, configfile, umask=None)
|
||||
m.setServiceParent(application)
|
36
build_files/buildbot-lts/docker/docker-compose.yml
Normal file
36
build_files/buildbot-lts/docker/docker-compose.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
version: '1'
|
||||
services:
|
||||
buildbot:
|
||||
image: buildbot/buildbot-master:master
|
||||
env_file:
|
||||
- db.env
|
||||
environment:
|
||||
- BUILDBOT_CONFIG_DIR=config
|
||||
- BUILDBOT_CONFIG_URL=https://github.com/buildbot/buildbot-docker-example-config/archive/master.tar.gz
|
||||
- BUILDBOT_WORKER_PORT=9989
|
||||
- BUILDBOT_WEB_URL=http://localhost:8010/
|
||||
- BUILDBOT_WEB_PORT=tcp:port=8010
|
||||
links:
|
||||
- db
|
||||
depends_on:
|
||||
- db
|
||||
ports:
|
||||
- "8010:8010"
|
||||
db:
|
||||
env_file:
|
||||
- db.env
|
||||
image: "postgres:9.4"
|
||||
expose:
|
||||
- 5432
|
||||
|
||||
worker:
|
||||
image: "buildbot/buildbot-worker:master"
|
||||
environment:
|
||||
BUILDMASTER: buildbot
|
||||
BUILDMASTER_PORT: 9989
|
||||
WORKERNAME: lts-worker
|
||||
WORKERPASS: pass
|
||||
WORKER_ENVIRONMENT_BLACKLIST: DOCKER_BUILDBOT* BUILDBOT_ENV_* BUILDBOT_1* WORKER_ENVIRONMENT_BLACKLIST
|
||||
|
||||
links:
|
||||
- buildbot
|
18
build_files/buildbot-lts/docker/docker-entrypoint.sh
Executable file
18
build_files/buildbot-lts/docker/docker-entrypoint.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
buildbot upgrade-master .
|
||||
|
||||
chown buildbot /var/lib/buildbot/
|
||||
chown buildbot /var/lib/buildbot/.ssh/
|
||||
chown -R buildbot /var/lib/buildbot/*
|
||||
|
||||
if [ -S /var/run/docker.sock ]
|
||||
then
|
||||
group=$(stat -c '%g' /var/run/docker.sock)
|
||||
else
|
||||
group=buildbot
|
||||
fi
|
||||
|
||||
gosu buildbot:$group "$@"
|
240
build_files/buildbot-lts/docker/master.cfg
Normal file
240
build_files/buildbot-lts/docker/master.cfg
Normal file
@@ -0,0 +1,240 @@
|
||||
# -*- python -*-
|
||||
# ex: set filetype=python:
|
||||
|
||||
import os
|
||||
|
||||
from buildbot.plugins import *
|
||||
|
||||
# This is a sample buildmaster config file. It must be installed as
|
||||
# 'master.cfg' in your buildmaster's base directory.
|
||||
|
||||
# This is the dictionary that the buildmaster pays attention to. We also use
|
||||
# a shorter alias to save typing.
|
||||
c = BuildmasterConfig = {}
|
||||
|
||||
####### WORKERS
|
||||
|
||||
# The 'workers' list defines the set of recognized workers. Each element is
|
||||
# a Worker object, specifying a unique worker name and password. The same
|
||||
# worker name and password must be configured on the worker.
|
||||
|
||||
c['workers'] = [worker.Worker("lts-worker", 'secret')]
|
||||
|
||||
if 'BUILDBOT_MQ_URL' in os.environ:
|
||||
c['mq'] = {
|
||||
'type' : 'wamp',
|
||||
'router_url': os.environ['BUILDBOT_MQ_URL'],
|
||||
'realm': os.environ.get('BUILDBOT_MQ_REALM', 'buildbot').decode('utf-8'),
|
||||
'debug' : 'BUILDBOT_MQ_DEBUG' in os.environ,
|
||||
'debug_websockets' : 'BUILDBOT_MQ_DEBUG' in os.environ,
|
||||
'debug_lowlevel' : 'BUILDBOT_MQ_DEBUG' in os.environ,
|
||||
}
|
||||
# 'protocols' contains information about protocols which master will use for
|
||||
# communicating with workers. You must define at least 'port' option that workers
|
||||
# could connect to your master with this protocol.
|
||||
# 'port' must match the value configured into the workers (with their
|
||||
# --master option)
|
||||
c['protocols'] = {'pb': {'port': os.environ.get("BUILDBOT_WORKER_PORT", 9989)}}
|
||||
|
||||
####### CHANGESOURCES
|
||||
|
||||
# the 'change_source' setting tells the buildmaster how it should find out
|
||||
# about source code changes. We don't build when sources change.
|
||||
c['change_source'] = []
|
||||
|
||||
####### SCHEDULERS
|
||||
|
||||
# Configure the Schedulers, which decide how to react to incoming changes. In this
|
||||
# case, just kick off a 'runtests' build
|
||||
|
||||
c['schedulers'] = [
|
||||
schedulers.ForceScheduler(
|
||||
name="build",
|
||||
builderNames=["release-blender-283"],
|
||||
properties=[
|
||||
util.StringParameter(
|
||||
name="blender_version",
|
||||
label="Version of blender.",
|
||||
default="2.83"),
|
||||
util.StringParameter(
|
||||
name="blender_version_full",
|
||||
label="Version of blender (Full).",
|
||||
default="2.83.1")
|
||||
]
|
||||
),
|
||||
|
||||
schedulers.Triggerable(
|
||||
name="deploy-source-archive",
|
||||
builderNames=["deploy-source-archive"]
|
||||
),
|
||||
|
||||
schedulers.Triggerable(
|
||||
name="deploy-buildbot-packages",
|
||||
builderNames=["deploy-buildbot-packages"]
|
||||
),
|
||||
]
|
||||
|
||||
####### BUILDERS
|
||||
|
||||
# The 'builders' list defines the Builders, which tell Buildbot how to perform a build:
|
||||
# what steps, and which workers can execute them. Note that any particular build will
|
||||
# only take place on one worker.
|
||||
|
||||
deploy_source_archive_factory = util.BuildFactory()
|
||||
deploy_source_archive_factory.addStep(steps.Git(name="Checkout Blender Source", repourl='https://git.blender.org/blender.git', branch=util.Interpolate('blender-v%(prop:blender_version)s-release'), mode='full'))
|
||||
deploy_source_archive_factory.addStep(steps.ShellSequence(name="Make source archive", commands=[
|
||||
util.ShellArg(command=["make", "source_archive"], logfile='make_source_archive'),
|
||||
# The next two shell commands are only needed during development
|
||||
util.ShellArg(command=["mv", "blender-2.83.2-beta.tar.xz", util.Interpolate('blender-v%(prop:blender_version_full)s.tar.xz')]),
|
||||
util.ShellArg(command=["mv", "blender-2.83.2-beta.tar.xz.md5sum", util.Interpolate('blender-v%(prop:blender_version_full)s.tar.xz.md5sum')]),
|
||||
]))
|
||||
deploy_source_archive_factory.addStep(steps.FileUpload(
|
||||
name="Upload source archive",
|
||||
workersrc=util.Interpolate('blender-v%(prop:blender_version_full)s.tar.xz'),
|
||||
masterdest=util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-v%(prop:blender_version_full)s.tar.xz')))
|
||||
deploy_source_archive_factory.addStep(steps.FileUpload(
|
||||
name="Upload source archive checksum",
|
||||
workersrc=util.Interpolate('blender-v%(prop:blender_version_full)s.tar.xz.md5sum'),
|
||||
masterdest=util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-v%(prop:blender_version_full)s.tar.xz.md5sum')))
|
||||
deploy_source_archive_factory.addStep(steps.MasterShellCommand(
|
||||
name="Upload source archive",
|
||||
command=[
|
||||
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-v%(prop:blender_version_full)s.tar.xz'),
|
||||
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
|
||||
deploy_source_archive_factory.addStep(steps.MasterShellCommand(
|
||||
name="Upload windows64.zip build",
|
||||
command=[
|
||||
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-v%(prop:blender_version_full)s.tar.xz.md5sum'),
|
||||
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
|
||||
|
||||
deploy_buildbot_packages_factory = util.BuildFactory()
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Download linux64 build",
|
||||
command=[
|
||||
'wget', util.Interpolate('https://builder.blender.org/download/blender-%(prop:blender_version_full)s-linux64.tar.xz'),
|
||||
"-O", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-linux64.tar.xz')]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Download windows64.msi build",
|
||||
command=[
|
||||
'wget', util.Interpolate('https://builder.blender.org/download/blender-%(prop:blender_version_full)s-windows64.msi'),
|
||||
"-O", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-windows64.msi')]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Download windows64.zip build",
|
||||
command=[
|
||||
'wget', util.Interpolate('https://builder.blender.org/download/blender-%(prop:blender_version_full)s-windows64.zip'),
|
||||
"-O", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-windows64.zip')]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Download macOS build",
|
||||
command=[
|
||||
'wget', util.Interpolate('https://builder.blender.org/download/blender-%(prop:blender_version_full)s-macOS.dmg'),
|
||||
"-O", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-macOS.dmg')]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Create checksum (md5/sha256)",
|
||||
command=[
|
||||
'sh',
|
||||
'-C',
|
||||
'/var/lib/buildbot/bin/create_checksum.sh',
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-*'),
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s'),
|
||||
]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Upload linux64 build",
|
||||
command=[
|
||||
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-linux64.tar.xz'),
|
||||
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Upload windows64.msi build",
|
||||
command=[
|
||||
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-windows64.msi'),
|
||||
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Upload windows64.zip build",
|
||||
command=[
|
||||
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-windows64.zip'),
|
||||
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Upload macOS build",
|
||||
command=[
|
||||
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s-macOS.dmg'),
|
||||
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Upload md5 checksum",
|
||||
command=[
|
||||
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s.md5'),
|
||||
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
|
||||
deploy_buildbot_packages_factory.addStep(steps.MasterShellCommand(
|
||||
name="Upload sha256 checksum",
|
||||
command=[
|
||||
'sh', '-C', '/var/lib/buildbot/bin/upload_file.sh',
|
||||
util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s/blender-%(prop:blender_version_full)s.sha256'),
|
||||
util.Interpolate('/data/www/vhosts/download.blender.org/ftp/jeroen/')]))
|
||||
|
||||
factory = util.BuildFactory()
|
||||
factory.addStep(steps.MasterShellCommand(name="Init release folder", command=["mkdir", "-p", util.Interpolate('/var/lib/buildbot/builds//blender-v%(prop:blender_version_full)s')]))
|
||||
factory.addStep(steps.Trigger(
|
||||
name='Deploy',
|
||||
schedulerNames=[
|
||||
'deploy-source-archive',
|
||||
'deploy-buildbot-packages',
|
||||
],
|
||||
waitForFinish=True,
|
||||
set_properties={
|
||||
'blender_version_full': util.Property('blender_version_full'),
|
||||
'blender_version': util.Property('blender_version'),
|
||||
}
|
||||
))
|
||||
|
||||
# Download builds from builder.blender.org
|
||||
c['builders'] = [
|
||||
util.BuilderConfig(name="release-blender-283",
|
||||
workernames=["lts-worker"],
|
||||
factory=factory),
|
||||
util.BuilderConfig(name="deploy-source-archive",
|
||||
workernames=["lts-worker"],
|
||||
factory=deploy_source_archive_factory),
|
||||
util.BuilderConfig(name="deploy-buildbot-packages",
|
||||
workernames=["lts-worker"],
|
||||
factory=deploy_buildbot_packages_factory),
|
||||
]
|
||||
|
||||
####### STATUS TARGETS
|
||||
|
||||
# 'status' is a list of Status Targets. The results of each build will be
|
||||
# pushed to these targets. buildbot/status/*.py has a variety to choose from,
|
||||
# like IRC bots.
|
||||
|
||||
# c['status'] = []
|
||||
|
||||
####### PROJECT IDENTITY
|
||||
|
||||
# the 'title' string will appear at the top of this buildbot installation's
|
||||
# home pages (linked to the 'titleURL').
|
||||
|
||||
c['title'] = "Blender Release LTS"
|
||||
c['titleURL'] = "https://www.blender.org/download/lts/"
|
||||
|
||||
# the 'buildbotURL' string should point to the location where the buildbot's
|
||||
# internal web server is visible. This typically uses the port number set in
|
||||
# the 'www' entry below, but with an externally-visible host name which the
|
||||
# buildbot cannot figure out without some help.
|
||||
|
||||
c['buildbotURL'] = os.environ.get("BUILDBOT_WEB_URL", "http://localhost:8010/")
|
||||
|
||||
# minimalistic config to activate new web UI
|
||||
c['www'] = dict(port=os.environ.get("BUILDBOT_WEB_PORT", 8010),
|
||||
plugins=dict(waterfall_view={}, console_view={}))
|
||||
|
||||
####### DB URL
|
||||
|
||||
c['db'] = {
|
||||
# This specifies what database buildbot uses to store its state. You can leave
|
||||
# this at its default for all but the largest installations.
|
||||
'db_url' : os.environ.get("BUILDBOT_DB_URL", "sqlite://").format(**os.environ),
|
||||
}
|
27
build_files/buildbot-lts/docker/worker/Dockerfile
Normal file
27
build_files/buildbot-lts/docker/worker/Dockerfile
Normal file
@@ -0,0 +1,27 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN set -ex; \
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
git \
|
||||
wget \
|
||||
python3-dev \
|
||||
python3-pip \
|
||||
python3-setuptools \
|
||||
python3-wheel \
|
||||
; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV BUILDBOT_VERSION 2.5.0
|
||||
RUN pip3 install --upgrade pip && \
|
||||
pip --no-cache-dir install twisted[tls] && \
|
||||
pip --no-cache-dir install buildbot_worker==$BUILDBOT_VERSION
|
||||
|
||||
RUN useradd --create-home --home-dir=/var/lib/buildbot buildbot
|
||||
WORKDIR /var/lib/buildbot
|
||||
USER buildbot
|
||||
|
||||
COPY buildbot.tac .
|
||||
|
||||
CMD ["twistd", "--pidfile=", "--nodaemon", "--python=buildbot.tac"]
|
39
build_files/buildbot-lts/docker/worker/buildbot.tac
Normal file
39
build_files/buildbot-lts/docker/worker/buildbot.tac
Normal file
@@ -0,0 +1,39 @@
|
||||
import fnmatch
|
||||
import os
|
||||
import sys
|
||||
|
||||
from twisted.application import service
|
||||
from twisted.python.log import FileLogObserver
|
||||
from twisted.python.log import ILogObserver
|
||||
|
||||
from buildbot_worker.bot import Worker
|
||||
|
||||
# setup worker
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
application = service.Application('buildbot-worker')
|
||||
|
||||
|
||||
application.setComponent(ILogObserver, FileLogObserver(sys.stdout).emit)
|
||||
# and worker on the same process!
|
||||
buildmaster_host = os.environ.get("BUILDMASTER", 'localhost')
|
||||
port = int(os.environ.get("BUILDMASTER_PORT", 9989))
|
||||
workername = os.environ.get("WORKERNAME", 'docker')
|
||||
passwd = os.environ.get("WORKERPASS")
|
||||
|
||||
# delete the password from the environ so that it is not leaked in the log
|
||||
blacklist = os.environ.get("WORKER_ENVIRONMENT_BLACKLIST", "WORKERPASS").split()
|
||||
for name in list(os.environ.keys()):
|
||||
for toremove in blacklist:
|
||||
if fnmatch.fnmatch(name, toremove):
|
||||
del os.environ[name]
|
||||
|
||||
keepalive = 600
|
||||
umask = None
|
||||
maxdelay = 300
|
||||
allow_shutdown = None
|
||||
maxretries = 10
|
||||
|
||||
s = Worker(buildmaster_host, port, workername, passwd, basedir,
|
||||
keepalive, umask=umask, maxdelay=maxdelay,
|
||||
allow_shutdown=allow_shutdown, maxRetries=maxretries)
|
||||
s.setServiceParent(application)
|
@@ -8,7 +8,7 @@ Code signing is done as part of INSTALL target, which makes it possible to sign
|
||||
files which are aimed into a bundle and coming from a non-signed source (such as
|
||||
libraries SVN).
|
||||
|
||||
This is achieved by specifying `slave_codesign.cmake` as a post-install script
|
||||
This is achieved by specifying `worker_codesign.cmake` as a post-install script
|
||||
run by CMake. This CMake script simply involves an utility script written in
|
||||
Python which takes care of an actual signing.
|
||||
|
||||
|
@@ -40,8 +40,8 @@ class Builder:
|
||||
|
||||
# Buildbot runs from build/ directory
|
||||
self.blender_dir = os.path.abspath(os.path.join('..', 'blender.git'))
|
||||
self.build_dir = os.path.abspath(os.path.join('..', 'build', name))
|
||||
self.install_dir = os.path.abspath(os.path.join('..', 'install', name))
|
||||
self.build_dir = os.path.abspath(os.path.join('..', 'build'))
|
||||
self.install_dir = os.path.abspath(os.path.join('..', 'install'))
|
||||
self.upload_dir = os.path.abspath(os.path.join('..', 'install'))
|
||||
|
||||
# Detect platform
|
||||
@@ -51,7 +51,7 @@ class Builder:
|
||||
elif name.startswith('linux'):
|
||||
self.platform = 'linux'
|
||||
if is_tool('scl'):
|
||||
self.command_prefix = ['scl', 'enable', 'devtoolset-6', '--']
|
||||
self.command_prefix = ['scl', 'enable', 'devtoolset-9', '--']
|
||||
else:
|
||||
self.command_prefix = []
|
||||
elif name.startswith('win'):
|
||||
|
@@ -48,6 +48,7 @@ import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import tarfile
|
||||
import uuid
|
||||
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
@@ -121,21 +122,10 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
# Consider this an input of the code signing server.
|
||||
unsigned_storage_dir: Path
|
||||
|
||||
# Information about archive which contains files which are to be signed.
|
||||
#
|
||||
# This archive is created by the buildbot worked and acts as an input for
|
||||
# the code signing server.
|
||||
unsigned_archive_info: ArchiveWithIndicator
|
||||
|
||||
# Storage where signed files are stored.
|
||||
# Consider this an output of the code signer server.
|
||||
signed_storage_dir: Path
|
||||
|
||||
# Information about archive which contains signed files.
|
||||
#
|
||||
# This archive is created by the code signing server.
|
||||
signed_archive_info: ArchiveWithIndicator
|
||||
|
||||
# Platform the code is currently executing on.
|
||||
platform: util.Platform
|
||||
|
||||
@@ -146,50 +136,44 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
|
||||
# Unsigned (signing server input) configuration.
|
||||
self.unsigned_storage_dir = absolute_shared_storage_dir / 'unsigned'
|
||||
self.unsigned_archive_info = ArchiveWithIndicator(
|
||||
self.unsigned_storage_dir, 'unsigned_files.tar', 'ready.stamp')
|
||||
|
||||
# Signed (signing server output) configuration.
|
||||
self.signed_storage_dir = absolute_shared_storage_dir / 'signed'
|
||||
self.signed_archive_info = ArchiveWithIndicator(
|
||||
self.signed_storage_dir, 'signed_files.tar', 'ready.stamp')
|
||||
|
||||
self.platform = util.get_current_platform()
|
||||
|
||||
"""
|
||||
General note on cleanup environment functions.
|
||||
|
||||
It is expected that there is only one instance of the code signer server
|
||||
running for a given input/output directory, and that it serves a single
|
||||
buildbot worker.
|
||||
By its nature, a buildbot worker only produces one build at a time and
|
||||
never performs concurrent builds.
|
||||
This leads to a conclusion that when starting in a clean environment
|
||||
there shouldn't be any archives remaining from a previous build.
|
||||
|
||||
However, it is possible to have various failure scenarios which might
|
||||
leave the environment in a non-clean state:
|
||||
|
||||
- Network hiccup which makes buildbot worker to stop current build
|
||||
and re-start it after connection to server is re-established.
|
||||
|
||||
Note, this could also happen during buildbot server maintenance.
|
||||
|
||||
- Signing server might get restarted due to updates or other reasons.
|
||||
|
||||
Requiring manual interaction in such cases is not something good to
|
||||
require, so here we simply assume that the system is used the way it is
|
||||
intended to and restore environment to a prestine clean state.
|
||||
"""
|
||||
|
||||
def cleanup_environment_for_builder(self) -> None:
|
||||
self.unsigned_archive_info.clean()
|
||||
self.signed_archive_info.clean()
|
||||
# TODO(sergey): Revisit need of cleaning up the existing files.
|
||||
# In practice it wasn't so helpful, and with multiple clients
|
||||
# talking to the same server it becomes even mor etricky.
|
||||
pass
|
||||
|
||||
def cleanup_environment_for_signing_server(self) -> None:
|
||||
# Don't clear the requested to-be-signed archive since we might be
|
||||
# restarting signing machine while the buildbot is busy.
|
||||
self.signed_archive_info.clean()
|
||||
# TODO(sergey): Revisit need of cleaning up the existing files.
|
||||
# In practice it wasn't so helpful, and with multiple clients
|
||||
# talking to the same server it becomes even mor etricky.
|
||||
pass
|
||||
|
||||
def generate_request_id(self) -> str:
|
||||
"""
|
||||
Generate an unique identifier for code signing request.
|
||||
"""
|
||||
return str(uuid.uuid4())
|
||||
|
||||
def archive_info_for_request_id(
|
||||
self, path: Path, request_id: str) -> ArchiveWithIndicator:
|
||||
return ArchiveWithIndicator(
|
||||
path, f'{request_id}.tar', f'{request_id}.ready')
|
||||
|
||||
def signed_archive_info_for_request_id(
|
||||
self, request_id: str) -> ArchiveWithIndicator:
|
||||
return self.archive_info_for_request_id(
|
||||
self.signed_storage_dir, request_id)
|
||||
|
||||
def unsigned_archive_info_for_request_id(
|
||||
self, request_id: str) -> ArchiveWithIndicator:
|
||||
return self.archive_info_for_request_id(
|
||||
self.unsigned_storage_dir, request_id)
|
||||
|
||||
############################################################################
|
||||
# Buildbot worker side helpers.
|
||||
@@ -232,7 +216,7 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
if self.check_file_is_to_be_signed(file)]
|
||||
return files_to_be_signed
|
||||
|
||||
def wait_for_signed_archive_or_die(self) -> None:
|
||||
def wait_for_signed_archive_or_die(self, request_id) -> None:
|
||||
"""
|
||||
Wait until archive with signed files is available.
|
||||
|
||||
@@ -240,13 +224,19 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
is still no responce from the signing server the application will exit
|
||||
with a non-zero exit code.
|
||||
"""
|
||||
|
||||
signed_archive_info = self.signed_archive_info_for_request_id(
|
||||
request_id)
|
||||
unsigned_archive_info = self.unsigned_archive_info_for_request_id(
|
||||
request_id)
|
||||
|
||||
timeout_in_seconds = self.config.TIMEOUT_IN_SECONDS
|
||||
time_start = time.monotonic()
|
||||
while not self.signed_archive_info.is_ready():
|
||||
while not signed_archive_info.is_ready():
|
||||
time.sleep(1)
|
||||
time_slept_in_seconds = time.monotonic() - time_start
|
||||
if time_slept_in_seconds > timeout_in_seconds:
|
||||
self.unsigned_archive_info.clean()
|
||||
unsigned_archive_info.clean()
|
||||
raise SystemExit("Signing server didn't finish signing in "
|
||||
f"{timeout_in_seconds} seconds, dying :(")
|
||||
|
||||
@@ -303,13 +293,19 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
return
|
||||
logger_builder.info('Found %d files to sign.', len(files))
|
||||
|
||||
request_id = self.generate_request_id()
|
||||
signed_archive_info = self.signed_archive_info_for_request_id(
|
||||
request_id)
|
||||
unsigned_archive_info = self.unsigned_archive_info_for_request_id(
|
||||
request_id)
|
||||
|
||||
pack_files(files=files,
|
||||
archive_filepath=self.unsigned_archive_info.archive_filepath)
|
||||
self.unsigned_archive_info.tag_ready()
|
||||
archive_filepath=unsigned_archive_info.archive_filepath)
|
||||
unsigned_archive_info.tag_ready()
|
||||
|
||||
# Wait for the signing server to finish signing.
|
||||
logger_builder.info('Waiting signing server to sign the files...')
|
||||
self.wait_for_signed_archive_or_die()
|
||||
self.wait_for_signed_archive_or_die(request_id)
|
||||
|
||||
# Extract signed files from archive and move files to final location.
|
||||
with TemporaryDirectory(prefix='blender-buildbot-') as temp_dir_str:
|
||||
@@ -317,7 +313,7 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
|
||||
logger_builder.info('Extracting signed files from archive...')
|
||||
extract_files(
|
||||
archive_filepath=self.signed_archive_info.archive_filepath,
|
||||
archive_filepath=signed_archive_info.archive_filepath,
|
||||
extraction_dir=unpacked_signed_files_dir)
|
||||
|
||||
destination_dir = path
|
||||
@@ -327,19 +323,44 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
unpacked_signed_files_dir, destination_dir)
|
||||
|
||||
logger_builder.info('Removing archive with signed files...')
|
||||
self.signed_archive_info.clean()
|
||||
signed_archive_info.clean()
|
||||
|
||||
############################################################################
|
||||
# Signing server side helpers.
|
||||
|
||||
def wait_for_sign_request(self) -> None:
|
||||
def wait_for_sign_request(self) -> str:
|
||||
"""
|
||||
Wait for the buildbot to request signing of an archive.
|
||||
|
||||
Returns an identifier of signing request.
|
||||
"""
|
||||
|
||||
# TOOD(sergey): Support graceful shutdown on Ctrl-C.
|
||||
while not self.unsigned_archive_info.is_ready():
|
||||
|
||||
logger_server.info(
|
||||
f'Waiting for a request directory {self.unsigned_storage_dir} to appear.')
|
||||
while not self.unsigned_storage_dir.exists():
|
||||
time.sleep(1)
|
||||
|
||||
logger_server.info(
|
||||
'Waiting for a READY indicator of any signing request.')
|
||||
request_id = None
|
||||
while request_id is None:
|
||||
for file in self.unsigned_storage_dir.iterdir():
|
||||
if file.suffix != '.ready':
|
||||
continue
|
||||
request_id = file.stem
|
||||
logger_server.info(f'Found READY for request ID {request_id}.')
|
||||
if request_id is None:
|
||||
time.sleep(1)
|
||||
|
||||
unsigned_archive_info = self.unsigned_archive_info_for_request_id(
|
||||
request_id)
|
||||
while not unsigned_archive_info.is_ready():
|
||||
time.sleep(1)
|
||||
|
||||
return request_id
|
||||
|
||||
@abc.abstractmethod
|
||||
def sign_all_files(self, files: List[AbsoluteAndRelativeFileName]) -> None:
|
||||
"""
|
||||
@@ -348,7 +369,7 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
NOTE: Signing should happen in-place.
|
||||
"""
|
||||
|
||||
def run_signing_pipeline(self):
|
||||
def run_signing_pipeline(self, request_id: str):
|
||||
"""
|
||||
Run the full signing pipeline starting from the point when buildbot
|
||||
worker have requested signing.
|
||||
@@ -360,9 +381,14 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
with TemporaryDirectory(prefix='blender-codesign-') as temp_dir_str:
|
||||
temp_dir = Path(temp_dir_str)
|
||||
|
||||
signed_archive_info = self.signed_archive_info_for_request_id(
|
||||
request_id)
|
||||
unsigned_archive_info = self.unsigned_archive_info_for_request_id(
|
||||
request_id)
|
||||
|
||||
logger_server.info('Extracting unsigned files from archive...')
|
||||
extract_files(
|
||||
archive_filepath=self.unsigned_archive_info.archive_filepath,
|
||||
archive_filepath=unsigned_archive_info.archive_filepath,
|
||||
extraction_dir=temp_dir)
|
||||
|
||||
logger_server.info('Collecting all files which needs signing...')
|
||||
@@ -374,11 +400,11 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
|
||||
logger_server.info('Packing signed files...')
|
||||
pack_files(files=files,
|
||||
archive_filepath=self.signed_archive_info.archive_filepath)
|
||||
self.signed_archive_info.tag_ready()
|
||||
archive_filepath=signed_archive_info.archive_filepath)
|
||||
signed_archive_info.tag_ready()
|
||||
|
||||
logger_server.info('Removing signing request...')
|
||||
self.unsigned_archive_info.clean()
|
||||
unsigned_archive_info.clean()
|
||||
|
||||
logger_server.info('Signing is complete.')
|
||||
|
||||
@@ -389,11 +415,11 @@ class BaseCodeSigner(metaclass=abc.ABCMeta):
|
||||
while True:
|
||||
logger_server.info('Waiting for the signing request in %s...',
|
||||
self.unsigned_storage_dir)
|
||||
self.wait_for_sign_request()
|
||||
request_id = self.wait_for_sign_request()
|
||||
|
||||
logger_server.info(
|
||||
'Got signing request, beging signign procedure.')
|
||||
self.run_signing_pipeline()
|
||||
f'Beging signign procedure for request ID {request_id}.')
|
||||
self.run_signing_pipeline(request_id)
|
||||
|
||||
############################################################################
|
||||
# Command executing.
|
||||
|
@@ -1,37 +0,0 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# Runs on buildbot slave, rsync zip directly to buildbot server rather
|
||||
# than using upload which is much slower
|
||||
|
||||
import buildbot_utils
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
builder = buildbot_utils.create_builder_from_arguments()
|
||||
|
||||
# rsync, this assumes ssh keys are setup so no password is needed
|
||||
local_zip = "buildbot_upload.zip"
|
||||
remote_folder = "builder.blender.org:/data/buildbot-master/uploaded/"
|
||||
remote_zip = remote_folder + "buildbot_upload_" + builder.name + ".zip"
|
||||
|
||||
command = ["rsync", "-avz", local_zip, remote_zip]
|
||||
buildbot_utils.call(command)
|
@@ -30,7 +30,7 @@ from tempfile import TemporaryDirectory, NamedTemporaryFile
|
||||
from typing import List
|
||||
|
||||
BUILDBOT_DIRECTORY = Path(__file__).absolute().parent
|
||||
CODESIGN_SCRIPT = BUILDBOT_DIRECTORY / 'slave_codesign.py'
|
||||
CODESIGN_SCRIPT = BUILDBOT_DIRECTORY / 'worker_codesign.py'
|
||||
BLENDER_GIT_ROOT_DIRECTORY = BUILDBOT_DIRECTORY.parent.parent
|
||||
DARWIN_DIRECTORY = BLENDER_GIT_ROOT_DIRECTORY / 'release' / 'darwin'
|
||||
|
@@ -33,7 +33,7 @@ else()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_LIST_DIR}/slave_codesign.py"
|
||||
COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_LIST_DIR}/worker_codesign.py"
|
||||
"${CMAKE_INSTALL_PREFIX}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
RESULT_VARIABLE exit_code
|
@@ -25,7 +25,7 @@ import buildbot_utils
|
||||
|
||||
def get_cmake_options(builder):
|
||||
post_install_script = os.path.join(
|
||||
builder.blender_dir, 'build_files', 'buildbot', 'slave_codesign.cmake')
|
||||
builder.blender_dir, 'build_files', 'buildbot', 'worker_codesign.cmake')
|
||||
|
||||
config_file = "build_files/cmake/config/blender_release.cmake"
|
||||
options = ['-DCMAKE_BUILD_TYPE:STRING=Release',
|
||||
@@ -35,7 +35,7 @@ def get_cmake_options(builder):
|
||||
options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=x86_64')
|
||||
options.append('-DCMAKE_OSX_DEPLOYMENT_TARGET=10.9')
|
||||
elif builder.platform == 'win':
|
||||
options.extend(['-G', 'Visual Studio 15 2017 Win64'])
|
||||
options.extend(['-G', 'Visual Studio 16 2019', '-A', 'x64'])
|
||||
options.extend(['-DPOSTINSTALL_SCRIPT:PATH=' + post_install_script])
|
||||
elif builder.platform == 'linux':
|
||||
config_file = "build_files/buildbot/config/blender_linux.cmake"
|
@@ -18,7 +18,7 @@
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
# Runs on buildbot slave, creating a release package using the build
|
||||
# Runs on buildbot worker, creating a release package using the build
|
||||
# system and zipping it into buildbot_upload.zip. This is then uploaded
|
||||
# to the master in the next buildbot step.
|
||||
|
||||
@@ -110,7 +110,7 @@ def pack_mac(builder):
|
||||
|
||||
release_dir = os.path.join(builder.blender_dir, 'release', 'darwin')
|
||||
buildbot_dir = os.path.join(builder.blender_dir, 'build_files', 'buildbot')
|
||||
bundle_script = os.path.join(buildbot_dir, 'slave_bundle_dmg.py')
|
||||
bundle_script = os.path.join(buildbot_dir, 'worker_bundle_dmg.py')
|
||||
|
||||
command = [bundle_script]
|
||||
command += ['--dmg', package_filepath]
|
@@ -1,65 +0,0 @@
|
||||
# - Find HDF5 library
|
||||
# Find the native HDF5 includes and libraries
|
||||
# This module defines
|
||||
# HDF5_INCLUDE_DIRS, where to find hdf5.h, Set when HDF5_INCLUDE_DIR is found.
|
||||
# HDF5_LIBRARIES, libraries to link against to use HDF5.
|
||||
# HDF5_ROOT_DIR, The base directory to search for HDF5.
|
||||
# This can also be an environment variable.
|
||||
# HDF5_FOUND, If false, do not try to use HDF5.
|
||||
#
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2016 Blender Foundation.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
|
||||
# If HDF5_ROOT_DIR was defined in the environment, use it.
|
||||
IF(NOT HDF5_ROOT_DIR AND NOT $ENV{HDF5_ROOT_DIR} STREQUAL "")
|
||||
SET(HDF5_ROOT_DIR $ENV{HDF5_ROOT_DIR})
|
||||
ENDIF()
|
||||
|
||||
SET(_hdf5_SEARCH_DIRS
|
||||
${HDF5_ROOT_DIR}
|
||||
/opt/lib/hdf5
|
||||
)
|
||||
|
||||
FIND_LIBRARY(HDF5_LIBRARY
|
||||
NAMES
|
||||
hdf5
|
||||
HINTS
|
||||
${_hdf5_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
|
||||
FIND_PATH(HDF5_INCLUDE_DIR
|
||||
NAMES
|
||||
hdf5.h
|
||||
HINTS
|
||||
${_hdf5_SEARCH_DIRS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set HDF5_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(HDF5 DEFAULT_MSG HDF5_LIBRARY HDF5_INCLUDE_DIR)
|
||||
|
||||
IF(HDF5_FOUND)
|
||||
SET(HDF5_LIBRARIES ${HDF5_LIBRARY})
|
||||
SET(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR})
|
||||
ENDIF(HDF5_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
HDF5_INCLUDE_DIR
|
||||
HDF5_LIBRARY
|
||||
)
|
||||
|
||||
UNSET(_hdf5_SEARCH_DIRS)
|
@@ -48,7 +48,14 @@ SET(_openimagedenoise_FIND_COMPONENTS
|
||||
# These are needed when building statically
|
||||
SET(_openimagedenoise_FIND_STATIC_COMPONENTS
|
||||
common
|
||||
|
||||
# These additional library names change between versions, we list all of them
|
||||
# so builds work with multiple versions. Missing libraries are skipped.
|
||||
dnnl_cpu
|
||||
dnnl_common
|
||||
dnnl_cpu # Second time because of circular dependency
|
||||
mkldnn
|
||||
dnnl
|
||||
)
|
||||
|
||||
SET(_openimagedenoise_LIBRARIES)
|
||||
|
@@ -11,6 +11,7 @@ set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_EMBREE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_DRACO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
|
||||
|
@@ -15,6 +15,7 @@ set(WITH_CODEC_AVI OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_EMBREE OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_DEVICE_OPTIX OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_DRACO OFF CACHE BOOL "" FORCE)
|
||||
|
@@ -12,6 +12,7 @@ set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_EMBREE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_DRACO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
|
||||
|
@@ -437,7 +437,6 @@ function(SETUP_LIBDIRS)
|
||||
|
||||
if(WITH_ALEMBIC)
|
||||
link_directories(${ALEMBIC_LIBPATH})
|
||||
link_directories(${HDF5_LIBPATH})
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_WAYLAND)
|
||||
|
@@ -265,14 +265,8 @@ endif()
|
||||
if(WITH_ALEMBIC)
|
||||
find_package_wrapper(Alembic)
|
||||
|
||||
if(WITH_ALEMBIC_HDF5)
|
||||
set(HDF5_ROOT_DIR ${LIBDIR}/hdf5)
|
||||
find_package_wrapper(HDF5)
|
||||
endif()
|
||||
|
||||
if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND))
|
||||
if(NOT ALEMBIC_FOUND)
|
||||
set(WITH_ALEMBIC OFF)
|
||||
set(WITH_ALEMBIC_HDF5 OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@@ -539,10 +539,10 @@ if(WITH_OPENIMAGEDENOISE)
|
||||
set(OPENIMAGEDENOISE_LIBRARIES
|
||||
optimized ${OPENIMAGEDENOISE_LIBPATH}/OpenImageDenoise.lib
|
||||
optimized ${OPENIMAGEDENOISE_LIBPATH}/common.lib
|
||||
optimized ${OPENIMAGEDENOISE_LIBPATH}/mkldnn.lib
|
||||
optimized ${OPENIMAGEDENOISE_LIBPATH}/dnnl.lib
|
||||
debug ${OPENIMAGEDENOISE_LIBPATH}/OpenImageDenoise_d.lib
|
||||
debug ${OPENIMAGEDENOISE_LIBPATH}/common_d.lib
|
||||
debug ${OPENIMAGEDENOISE_LIBPATH}/mkldnn_d.lib)
|
||||
debug ${OPENIMAGEDENOISE_LIBPATH}/dnnl_d.lib)
|
||||
set(OPENIMAGEDENOISE_DEFINITIONS)
|
||||
endif()
|
||||
|
||||
|
@@ -1,2 +1,2 @@
|
||||
Sphinx==3.0.3
|
||||
sphinx_rtd_theme==0.5.0rc1
|
||||
Sphinx==3.1.1
|
||||
sphinx_rtd_theme==0.5.0
|
||||
|
@@ -427,7 +427,7 @@ offers a set of extensive examples, including advanced features.
|
||||
|
||||
Return evaluator parameters
|
||||
|
||||
.. seealso:: `OpenGL Docs <https://www.opengl.org/sdk/docs/man2/xhtml/glGetMap.xml>`_
|
||||
.. seealso:: `OpenGL Docs <https://www.opengl.org/sdk/docs/man2/xhtml/glGetMap.xml>`__
|
||||
|
||||
:type target: Enumerated constant
|
||||
:arg target: Specifies the symbolic name of a map.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
..
|
||||
This document is appended to the auto generated bmesh api doc to avoid clogging up the C files with details.
|
||||
This document is appended to the auto generated BMesh API doc to avoid clogging up the C files with details.
|
||||
to test this run:
|
||||
./blender.bin -b -noaudio -P doc/python_api/sphinx_doc_gen.py -- \
|
||||
--partial bmesh* ; cd doc/python_api ; sphinx-build sphinx-in sphinx-out ; cd ../../
|
||||
@@ -19,25 +19,24 @@ Submodules:
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This API gives access the blenders internal mesh editing api, featuring geometry connectivity data and
|
||||
This API gives access the Blender's internal mesh editing API, featuring geometry connectivity data and
|
||||
access to editing operations such as split, separate, collapse and dissolve.
|
||||
|
||||
The features exposed closely follow the C API,
|
||||
giving python access to the functions used by blenders own mesh editing tools.
|
||||
giving Python access to the functions used by Blender's own mesh editing tools.
|
||||
|
||||
For an overview of BMesh data types and how they reference each other see:
|
||||
`BMesh Design Document <https://wiki.blender.org/index.php/Dev:Source/Modeling/BMesh/Design>`_ .
|
||||
`BMesh Design Document <https://wiki.blender.org/index.php/Dev:Source/Modeling/BMesh/Design>`__.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
**Disk** and **Radial** data is not exposed by the python api since this is for internal use only.
|
||||
**Disk** and **Radial** data is not exposed by the Python API since this is for internal use only.
|
||||
|
||||
|
||||
.. warning:: TODO items are...
|
||||
|
||||
* add access to BMesh **walkers**
|
||||
* add custom-data manipulation functions add/remove/rename.
|
||||
- add access to BMesh **walkers**.
|
||||
- add custom-data manipulation functions add, remove or rename.
|
||||
|
||||
|
||||
Example Script
|
||||
@@ -46,55 +45,52 @@ Example Script
|
||||
.. literalinclude:: __/__/__/release/scripts/templates_py/bmesh_simple.py
|
||||
|
||||
|
||||
Stand-Alone Module
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
Standalone Module
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The bmesh module is written to be standalone except for :mod:`mathutils`
|
||||
The BMesh module is written to be standalone except for :mod:`mathutils`
|
||||
which is used for vertex locations and normals.
|
||||
|
||||
The only other exception to this are when converting mesh data to and from :class:`bpy.types.Mesh`.
|
||||
|
||||
|
||||
Mesh Access
|
||||
-----------
|
||||
|
||||
There are 2 ways to access BMesh data, you can create a new BMesh by converting a mesh from
|
||||
:class:`bpy.types.BlendData.meshes` or by accessing the current edit mode mesh.
|
||||
see: :class:`bmesh.types.BMesh.from_mesh` and :mod:`bmesh.from_edit_mesh` respectively.
|
||||
There are two ways to access BMesh data, you can create a new BMesh by converting a mesh from
|
||||
:class:`bpy.types.BlendData.meshes` or by accessing the current Edit-Mode mesh.
|
||||
See: :class:`bmesh.types.BMesh.from_mesh` and :mod:`bmesh.from_edit_mesh` respectively.
|
||||
|
||||
When explicitly converting from mesh data python **owns** the data, that is to say -
|
||||
that the mesh only exists while python holds a reference to it,
|
||||
and the script is responsible for putting it back into a mesh data-block when the edits are done.
|
||||
When explicitly converting from mesh data Python **owns** the data, that means that
|
||||
the mesh only exists while Python holds a reference to it.
|
||||
The script is responsible for putting it back into a mesh data-block when the edits are done.
|
||||
|
||||
Note that unlike :mod:`bpy`, a BMesh does not necessarily correspond to data in the currently open blend file,
|
||||
Note that unlike :mod:`bpy`, a BMesh does not necessarily correspond to data in the currently open blend-file,
|
||||
a BMesh can be created, edited and freed without the user ever seeing or having access to it.
|
||||
Unlike edit mode, the bmesh module can use multiple BMesh instances at once.
|
||||
Unlike Edit-Mode, the BMesh module can use multiple BMesh instances at once.
|
||||
|
||||
Take care when dealing with multiple BMesh instances since the mesh data can use a lot of memory, while a mesh that
|
||||
python owns will be freed in when the script holds no references to it,
|
||||
its good practice to call :class:`bmesh.types.BMesh.free` which will remove all the mesh data immediately and disable
|
||||
further access.
|
||||
Take care when dealing with multiple BMesh instances since the mesh data can use a lot of memory.
|
||||
While a mesh that the Python script owns will be freed when the script holds no references to it,
|
||||
it's good practice to call :class:`bmesh.types.BMesh.free` which will remove all the mesh data immediately
|
||||
and disable further access.
|
||||
|
||||
|
||||
EditMode Tessellation
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
Edit-Mode Tessellation
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When writing scripts that operate on editmode data you will normally want to re-calculate the tessellation after
|
||||
running the script, this needs to be called explicitly.
|
||||
|
||||
The BMesh its self does not store the triangulated faces, they are stored in the :class:`bpy.types.Mesh`,
|
||||
When writing scripts that operate on Edit-Mode data you will normally want to re-calculate the tessellation after
|
||||
running the script, this needs to be called explicitly.
|
||||
The BMesh itself does not store the triangulated faces, instead they are stored in the :class:`bpy.types.Mesh`,
|
||||
to refresh tessellation triangles call :class:`bpy.types.Mesh.calc_loop_triangles`.
|
||||
|
||||
|
||||
CustomData Access
|
||||
-----------------
|
||||
|
||||
BMesh has a unified way to access mesh attributes such as UV's vertex colors, shape keys, edge crease etc.
|
||||
BMesh has a unified way to access mesh attributes such as UVs, vertex colors, shape keys, edge crease, etc.
|
||||
This works by having a **layers** property on BMesh data sequences to access the custom data layers
|
||||
which can then be used to access the actual data on each vert, edge, face or loop.
|
||||
|
||||
This works by having a **layers** property on bmesh data sequences to access the custom data layers which can then be
|
||||
used to access the actual data on each vert/edge/face/loop.
|
||||
|
||||
Here are some examples ...
|
||||
Here are some examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -139,27 +135,27 @@ Here are some examples ...
|
||||
Keeping a Correct State
|
||||
-----------------------
|
||||
|
||||
When modeling in blender there are certain assumptions made about the state of the mesh.
|
||||
When modeling in Blender there are certain assumptions made about the state of the mesh:
|
||||
|
||||
* hidden geometry isn't selected.
|
||||
* when an edge is selected, its vertices are selected too.
|
||||
* when a face is selected, its edges and vertices are selected.
|
||||
* duplicate edges / faces don't exist.
|
||||
* faces have at least 3 vertices.
|
||||
- Hidden geometry isn't selected.
|
||||
- When an edge is selected, its vertices are selected too.
|
||||
- When a face is selected, its edges and vertices are selected.
|
||||
- Duplicate edges / faces don't exist.
|
||||
- Faces have at least three vertices.
|
||||
|
||||
To give developers flexibility these conventions are not enforced,
|
||||
however tools must leave the mesh in a valid state else other tools may behave incorrectly.
|
||||
|
||||
yet tools must leave the mesh in a valid state or else other tools may behave incorrectly.
|
||||
Any errors that arise from not following these conventions is considered a bug in the script,
|
||||
not a bug in blender.
|
||||
not a bug in Blender.
|
||||
|
||||
|
||||
Selection / Flushing
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As mentioned above, it is possible to create an invalid selection state
|
||||
(by selecting a state and then de-selecting one of its vertices's for example), mostly the best way to solve this is to
|
||||
flush the selection after performing a series of edits. this validates the selection state.
|
||||
(by selecting a state and then deselecting one of its vertices for example),
|
||||
mostly the best way to solve this is to flush the selection
|
||||
after performing a series of edits. This validates the selection state.
|
||||
|
||||
|
||||
Module Functions
|
||||
|
@@ -3,94 +3,84 @@
|
||||
Reference API Usage
|
||||
*******************
|
||||
|
||||
Blender has many interlinking data types which have an auto-generated reference api which often has the information
|
||||
Blender has many interlinking data types which have an auto-generated reference API which often has the information
|
||||
you need to write a script, but can be difficult to use.
|
||||
|
||||
This document is designed to help you understand how to use the reference api.
|
||||
This document is designed to help you understand how to use the reference API.
|
||||
|
||||
|
||||
Reference API Scope
|
||||
===================
|
||||
|
||||
The reference API covers :mod:`bpy.types`, which stores types accessed via :mod:`bpy.context` - *The user context*
|
||||
or :mod:`bpy.data` - *Blend file data*.
|
||||
The reference API covers :mod:`bpy.types`, which stores types accessed via :mod:`bpy.context` -- *the user context*
|
||||
or :mod:`bpy.data` -- *blend-file data*.
|
||||
|
||||
Other modules such as :mod:`bmesh` and :mod:`aud` are not using Blenders data API
|
||||
Other modules such as :mod:`bmesh` and :mod:`aud` are not using Blender's data API
|
||||
so this document doesn't apply to those modules.
|
||||
|
||||
|
||||
Data Access
|
||||
===========
|
||||
|
||||
The most common case for using the reference API is to find out how to access data in the blend file.
|
||||
|
||||
Before going any further its best to be aware of ID Data-Blocks in Blender since you will often find properties
|
||||
The most common case for using the reference API is to find out how to access data in the blend-file.
|
||||
Before going any further its best to be aware of ID data-blocks in Blender since you will often find properties
|
||||
relative to them.
|
||||
|
||||
|
||||
ID Data
|
||||
-------
|
||||
|
||||
ID Data-Blocks are used in Blender as top-level data containers.
|
||||
ID data-blocks are used in Blender as top-level data containers.
|
||||
From the user interface this isn't so obvious, but when developing you need to know about ID data-blocks.
|
||||
ID data types include Scene, Group, Object, Mesh, Workspace, World, Armature, Image and Texture.
|
||||
For a full list see the subclasses of :class:`bpy.types.ID`.
|
||||
|
||||
From the user interface this isn't so obvious, but when developing you need to know about ID Data-Blocks.
|
||||
Here are some characteristics ID data-blocks share:
|
||||
|
||||
ID data types include Scene, Group, Object, Mesh, Screen, World, Armature, Image and Texture.
|
||||
for a full list see the sub-classes of :class:`bpy.types.ID`
|
||||
|
||||
Here are some characteristics ID Data-Blocks share.
|
||||
|
||||
- ID's are blend file data, so loading a new blend file reloads an entire new set of Data-Blocks.
|
||||
- ID's can be accessed in Python from ``bpy.data.*``
|
||||
- IDs are blend-file data, so loading a new blend-file reloads an entire new set of data-blocks.
|
||||
- IDs can be accessed in Python from ``bpy.data.*``.
|
||||
- Each data-block has a unique ``.name`` attribute, displayed in the interface.
|
||||
- Animation data is stored in ID's ``.animation_data``.
|
||||
- ID's are the only data types that can be linked between blend files.
|
||||
- ID's can be added/copied and removed via Python.
|
||||
- ID's have their own garbage-collection system which frees unused ID's when saving.
|
||||
- When a data-block has a reference to some external data, this is typically an ID Data-Block.
|
||||
- Animation data is stored in IDs ``.animation_data``.
|
||||
- IDs are the only data types that can be linked between blend-files.
|
||||
- IDs can be added/copied and removed via Python.
|
||||
- IDs have their own garbage-collection system which frees unused IDs when saving.
|
||||
- When a data-block has a reference to some external data, this is typically an ID data-block.
|
||||
|
||||
|
||||
Simple Data Access
|
||||
------------------
|
||||
|
||||
Lets start with a simple case, say you want a python script to adjust the object's location.
|
||||
In this simple case a Python script is used to adjust the object's location.
|
||||
Start by collecting the information where the data is located.
|
||||
|
||||
Start by finding this setting in the interface ``Properties Window -> Object -> Transform -> Location``
|
||||
|
||||
From the button you can right click and select **Online Python Reference**, this will link you to:
|
||||
:class:`bpy.types.Object.location`
|
||||
|
||||
Being an API reference, this link often gives little more information then the tool-tip, though some of the pages
|
||||
First find this setting in the interface ``Properties editor -> Object -> Transform -> Location``.
|
||||
From the button context menu select *Online Python Reference*, this will link you to:
|
||||
:class:`bpy.types.Object.location`.
|
||||
Being an API reference, this link often gives little more information then the tooltip, though some of the pages
|
||||
include examples (normally at the top of the page).
|
||||
But you now know that you have to use ``.location`` and that its an array of three floats.
|
||||
|
||||
At this point you may say *Now what?* - you know that you have to use ``.location`` and that its an array of 3 floats
|
||||
but you're still left wondering how to access this in a script.
|
||||
|
||||
So the next step is to find out where to access objects, go down to the bottom of the page to the **References**
|
||||
section, for objects there are many references, but one of the most common places to access objects is via the context.
|
||||
|
||||
It's easy to be overwhelmed at this point since there ``Object`` get referenced in so many places - modifiers,
|
||||
functions, textures and constraints.
|
||||
|
||||
So the next step is to find out where to access objects, go down to the bottom of the page to the references section,
|
||||
for objects there are many references, but one of the most common places to access objects is via the context.
|
||||
It's easy to be overwhelmed at this point since there ``Object`` get referenced in so many places:
|
||||
modifiers, functions, textures and constraints.
|
||||
But if you want to access any data the user has selected
|
||||
you typically only need to check the :mod:`bpy.context` references.
|
||||
|
||||
Even then, in this case there are quite a few though if you read over these - most are mode specific.
|
||||
If you happen to be writing a tool that only runs in weight paint mode, then using ``weight_paint_object``
|
||||
would be appropriate.
|
||||
However to access an item the user last selected, look for the ``active`` members,
|
||||
Having access to a single active member the user selects is a convention in Blender: eg. ``active_bone``,
|
||||
``active_pose_bone``, ``active_node`` ... and in this case we can use - ``active_object``.
|
||||
Even then, in this case there are quite a few though
|
||||
if you read over these you'll notice that most are mode specific.
|
||||
If you happen to be writing a tool that only runs in Weight Paint Mode,
|
||||
then using ``weight_paint_object`` would be appropriate.
|
||||
However, to access an item the user last selected, look for the ``active`` members,
|
||||
Having access to a single active member the user selects is a convention in Blender:
|
||||
e.g. ``active_bone``, ``active_pose_bone``, ``active_node``, etc. and in this case you can use ``active_object``.
|
||||
|
||||
|
||||
So now we have enough information to find the location of the active object.
|
||||
So now you have enough information to find the location of the active object.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bpy.context.active_object.location
|
||||
|
||||
You can type this into the python console to see the result.
|
||||
|
||||
You can type this into the Python console to see the result.
|
||||
The other common place to access objects in the reference is :class:`bpy.types.BlendData.objects`.
|
||||
|
||||
.. note::
|
||||
@@ -100,7 +90,7 @@ The other common place to access objects in the reference is :class:`bpy.types.B
|
||||
so the documentation points there.
|
||||
|
||||
|
||||
With :mod:`bpy.data.objects`, this is a collection of objects so you need to access one of its members.
|
||||
With :mod:`bpy.data.objects`, this is a collection of objects so you need to access one of its members:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -117,37 +107,34 @@ Here are some more complex examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# access a render layers samples
|
||||
bpy.context.scene.render.layers["RenderLayer"].samples
|
||||
# Access the number of samples for the Cycles render engine.
|
||||
bpy.context.scene.cycles.samples
|
||||
|
||||
# access to the current weight paint brush size
|
||||
# Access to the current weight paint brush size.
|
||||
bpy.context.tool_settings.weight_paint.brush.size
|
||||
|
||||
# check if the window is fullscreen
|
||||
# Check if the window is full-screen.
|
||||
bpy.context.window.screen.show_fullscreen
|
||||
|
||||
|
||||
As you can see there are times when you want to access data which is nested
|
||||
in a way that causes you to go through a few indirections.
|
||||
The properties are arranged to match how data is stored internally (in Blender's C code) which is often logical
|
||||
but not always quite what you would expect from using Blender.
|
||||
So this takes some time to learn, it helps you understand how data fits together in Blender
|
||||
which is important to know when writing scripts.
|
||||
|
||||
The properties are arranged to match how data is stored internally (in blenders C code) which is often logical but
|
||||
not always quite what you would expect from using Blender.
|
||||
|
||||
So this takes some time to learn, it helps you understand how data fits together in Blender which is important
|
||||
to know when writing scripts.
|
||||
|
||||
|
||||
When starting out scripting you will often run into the problem where you're not sure how to access the data you want.
|
||||
|
||||
There are a few ways to do this.
|
||||
When starting out scripting you will often run into the problem
|
||||
where you're not sure how to access the data you want.
|
||||
There are a few ways to do this:
|
||||
|
||||
- Use the Python console's auto-complete to inspect properties.
|
||||
*This can be hit-and-miss but has the advantage
|
||||
that you can easily see the values of properties and assign them to interactively see the results.*
|
||||
- Copy the Data-Path from the user interface.
|
||||
*Explained further in :ref:`Copy Data Path <info_data_path_copy>`*
|
||||
- Copy the data path from the user interface.
|
||||
*Explained further in* :ref:`Copy Data Path <info_data_path_copy>`.
|
||||
- Using the documentation to follow references.
|
||||
*Explained further in :ref:`Indirect Data Access <info_data_path_indirect>`*
|
||||
*Explained further in* :ref:`Indirect Data Access <info_data_path_indirect>`.
|
||||
|
||||
|
||||
.. _info_data_path_copy:
|
||||
@@ -155,42 +142,36 @@ There are a few ways to do this.
|
||||
Copy Data Path
|
||||
--------------
|
||||
|
||||
Blender can compute the Python string to a property which is shown in the tool-tip, on the line below ``Python: ...``,
|
||||
This saves having to use the API reference to click back up the references to find where data is accessed from.
|
||||
|
||||
There is a user-interface feature to copy the data-path which gives the path from an :class:`bpy.types.ID` data-block,
|
||||
Blender can compute the Python string to a property which is shown in the tooltip,
|
||||
on the line below ``Python: ...``. This saves having to open the API references to find where data is accessed from.
|
||||
In the context menu is a copy data-path tool which gives the path from an :class:`bpy.types.ID` data-block,
|
||||
to its property.
|
||||
|
||||
To see how this works we'll get the path to the Subdivision-Surface modifiers subdivision setting.
|
||||
|
||||
Start with the default scene and select the **Modifiers** tab, then add a **Subdivision-Surface** modifier to the cube.
|
||||
|
||||
Now hover your mouse over the button labeled **View**, The tool-tip includes :class:`bpy.types.SubsurfModifier.levels`
|
||||
but we want the path from the object to this property.
|
||||
To see how this works you'll get the path to the Subdivision Surface modifiers *Levels* setting.
|
||||
Start with the default scene and select the Modifiers tab, then add a Subdivision Surface modifier to the cube.
|
||||
Now hover your mouse over the button labeled *Levels Viewport*,
|
||||
The tooltip includes :class:`bpy.types.SubsurfModifier.levels` but you want the path from the object to this property.
|
||||
|
||||
Note that the text copied won't include the ``bpy.data.collection["name"].`` component since its assumed that
|
||||
you won't be doing collection look-ups on every access and typically you'll want to use the context rather
|
||||
then access each :class:`bpy.types.ID` instance by name.
|
||||
|
||||
|
||||
Type in the ID path into a Python console :mod:`bpy.context.active_object`.
|
||||
Include the trailing dot and don't hit "enter", yet.
|
||||
Include the trailing dot and don't execute the code, yet.
|
||||
|
||||
Now right-click on the button and select **Copy Data Path**, then paste the result into the console.
|
||||
|
||||
So now you should have the answer:
|
||||
Now in the button's context menu select *Copy Data Path*, then paste the result into the console:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bpy.context.active_object.modifiers["Subsurf"].levels
|
||||
|
||||
Hit "enter" and you'll get the current value of 1. Now try changing the value to 2:
|
||||
Press :kbd:`Return` and you'll get the current value of 1. Now try changing the value to 2:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bpy.context.active_object.modifiers["Subsurf"].levels = 2
|
||||
bpy.context.active_object.modifiers["Subsurf"].levels = 2
|
||||
|
||||
You can see the value update in the Subdivision-Surface modifier's UI as well as the cube.
|
||||
You can see the value update in the Subdivision Surface modifier's UI as well as the cube.
|
||||
|
||||
|
||||
.. _info_data_path_indirect:
|
||||
@@ -198,51 +179,45 @@ You can see the value update in the Subdivision-Surface modifier's UI as well as
|
||||
Indirect Data Access
|
||||
--------------------
|
||||
|
||||
For this example we'll go over something more involved, showing the steps to access the active sculpt brushes texture.
|
||||
This more advanced example shows the steps to access the active sculpt brushes texture.
|
||||
For example, if you want to access the texture of a brush via Python to adjust its ``contrast``.
|
||||
|
||||
Lets say we want to access the texture of a brush via Python, to adjust its ``contrast`` for example.
|
||||
#. Start in the default scene and enable Sculpt Mode from the 3D Viewport header.
|
||||
#. From the Sidebar expand the Brush Settings panel's *Texture* subpanel and add a new texture.
|
||||
*Notice the texture data-block menu itself doesn't have very useful links (you can check the tooltips).*
|
||||
#. The contrast setting isn't exposed in the Sidebar, so view the texture in the properties editor:
|
||||
|
||||
- Start in the default scene and enable 'Sculpt' mode from the 3D-View header.
|
||||
- From the toolbar expand the **Texture** panel and add a new texture.
|
||||
*Notice the texture button its self doesn't have very useful links (you can check the tooltips).*
|
||||
- The contrast setting isn't exposed in the sculpt toolbar, so view the texture in the properties panel...
|
||||
- In the properties editor select the Texture tab.
|
||||
- Select brush texture.
|
||||
- Expand the *Colors* panel to locate the *Contrast* number field.
|
||||
#. Open the context menu of the contrast field and select *Online Python Reference*.
|
||||
This takes you to ``bpy.types.Texture.contrast``. Now you can see that ``contrast`` is a property of texture.
|
||||
#. To find out how to access the texture from the brush check on the references at the bottom of the page.
|
||||
Sometimes there are many references, and it may take some guesswork to find the right one,
|
||||
but in this case it's ``Brush.texture``.
|
||||
|
||||
- In the properties button select the Texture context.
|
||||
- Select the Brush icon to show the brush texture.
|
||||
- Expand the *Colors* panel to locate the *Contrast* button.
|
||||
- Right click on the contrast button and select **Online Python Reference**
|
||||
This takes you to ``bpy.types.Texture.contrast``
|
||||
- Now we can see that ``contrast`` is a property of texture,
|
||||
so next we'll check on how to access the texture from the brush.
|
||||
- Check on the **References** at the bottom of the page, sometimes there are many references, and it may take
|
||||
some guess work to find the right one, but in this case its obviously ``Brush.texture``.
|
||||
#. Now you know that the texture can be accessed from ``bpy.data.brushes["BrushName"].texture``
|
||||
but normally you *won't* want to access the brush by name, instead you want to access the active brush.
|
||||
So the next step is to check on where brushes are accessed from via the references.
|
||||
In this case there it is simply ``bpy.context.brush``.
|
||||
|
||||
*Now we know that the texture can be accessed from* ``bpy.data.brushes["BrushName"].texture``
|
||||
*but normally you won't want to access the brush by name, so we'll see now to access the active brush instead.*
|
||||
- So the next step is to check on where brushes are accessed from via the **References**.
|
||||
In this case there is simply ``bpy.context.brush`` which is all we need.
|
||||
Now you can use the Python console to form the nested properties needed to access brush textures contrast:
|
||||
*Context -> Brush -> Texture -> Contrast*.
|
||||
|
||||
Now you can use the Python console to form the nested properties needed to access brush textures contrast,
|
||||
logically we now know.
|
||||
|
||||
*Context -> Brush -> Texture -> Contrast*
|
||||
|
||||
Since the attribute for each is given along the way we can compose the data path in the python console:
|
||||
Since the attribute for each is given along the way you can compose the data path in the Python console:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bpy.context.brush.texture.contrast
|
||||
|
||||
|
||||
There can be multiple ways to access the same data, which you choose often depends on the task.
|
||||
|
||||
An alternate path to access the same setting is...
|
||||
An alternate path to access the same setting is:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bpy.context.sculpt.brush.texture.contrast
|
||||
|
||||
Or access the brush directly...
|
||||
Or access the brush directly:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -251,27 +226,24 @@ Or access the brush directly...
|
||||
|
||||
If you are writing a user tool normally you want to use the :mod:`bpy.context` since the user normally expects
|
||||
the tool to operate on what they have selected.
|
||||
|
||||
For automation you are more likely to use :mod:`bpy.data` since you want to be able to access specific data and manipulate
|
||||
it, no matter what the user currently has the view set at.
|
||||
For automation you are more likely to use :mod:`bpy.data` since you want to be able to access specific data and
|
||||
manipulate it, no matter what the user currently has the view set at.
|
||||
|
||||
|
||||
Operators
|
||||
=========
|
||||
|
||||
Most key-strokes and buttons in Blender call an operator which is also exposed to python via :mod:`bpy.ops`,
|
||||
Most hotkeys and buttons in Blender call an operator which is also exposed to Python via :mod:`bpy.ops`.
|
||||
|
||||
To see the Python equivalent hover your mouse over the button and see the tool-tip,
|
||||
eg ``Python: bpy.ops.render.render()``,
|
||||
If there is no tool-tip or the ``Python:`` line is missing then this button is not using an operator and
|
||||
can't be accessed from Python.
|
||||
To see the Python equivalent hover your mouse over the button and see the tooltip,
|
||||
e.g ``Python: bpy.ops.render.render()``,
|
||||
If there is no tooltip or the ``Python:`` line is missing then this button is not using an operator
|
||||
and can't be accessed from Python.
|
||||
|
||||
|
||||
If you want to use this in a script you can press :kbd:`Control-C` while your mouse is over the button to copy it to the
|
||||
clipboard.
|
||||
|
||||
You can also right click on the button and view the **Online Python Reference**, this mainly shows arguments and
|
||||
their defaults however operators written in Python show their file and line number which may be useful if you
|
||||
If you want to use this in a script you can press :kbd:`Ctrl-C` while your mouse is over the button
|
||||
to copy it to the clipboard.
|
||||
You can also use button's context menu and view the *Online Python Reference*, this mainly shows arguments and
|
||||
their defaults, however, operators written in Python show their file and line number which may be useful if you
|
||||
are interested to check on the source code.
|
||||
|
||||
.. note::
|
||||
@@ -280,21 +252,18 @@ are interested to check on the source code.
|
||||
for more on this see :ref:`using operators <using_operators>`.
|
||||
|
||||
|
||||
Info View
|
||||
---------
|
||||
Info Editor
|
||||
-----------
|
||||
|
||||
Blender records operators you run and displays them in the **Info** space.
|
||||
This is located above the file-menu which can be dragged down to display its contents.
|
||||
Blender records operators you run and displays them in the Info editor.
|
||||
Select the Scripting workspace that comes default with Blender to see its output.
|
||||
You can perform some actions and see them show up -- delete a vertex for example.
|
||||
|
||||
Select the **Script** screen that comes default with Blender to see its output.
|
||||
You can perform some actions and see them show up - delete a vertex for example.
|
||||
|
||||
Each entry can be selected (Right-Mouse-Button),
|
||||
then copied :kbd:`Control-C`, usually to paste in the text editor or python console.
|
||||
Each entry can be selected, then copied :kbd:`Ctrl-C`, usually to paste in the text editor or Python console.
|
||||
|
||||
.. note::
|
||||
|
||||
Not all operators get registered for display,
|
||||
zooming the view for example isn't so useful to repeat so its excluded from the output.
|
||||
|
||||
To display *every* operator that runs see :ref:`Show All Operators <info_show_all_operators>`
|
||||
To display *every* operator that runs see :ref:`Show All Operators <info_show_all_operators>`.
|
||||
|
@@ -3,38 +3,34 @@
|
||||
Best Practice
|
||||
*************
|
||||
|
||||
When writing your own scripts python is great for new developers to pick up and become productive,
|
||||
but you can also pick up odd habits or at least write scripts that are not easy for others to understand.
|
||||
|
||||
When writing your own scripts Python is great for new developers to pick up and become productive,
|
||||
but you can also pick up bad practices or at least write scripts that are not easy for others to understand.
|
||||
For your own work this is of course fine,
|
||||
but if you want to collaborate with others or have your work included with blender there are practices we encourage.
|
||||
but if you want to collaborate with others or have your work included with Blender there are practices we encourage.
|
||||
|
||||
|
||||
Style Conventions
|
||||
=================
|
||||
|
||||
For Blender/Python development we have chosen to follow python suggested style guide to avoid mixing styles
|
||||
amongst our own scripts and make it easier to use python scripts from other projects.
|
||||
For Blender Python development we have chosen to follow Python suggested style guide to avoid mixing styles
|
||||
among our own scripts and make it easier to use Python scripts from other projects.
|
||||
Using our style guide for your own scripts makes it easier if you eventually want to contribute them to Blender.
|
||||
|
||||
Using our style guide for your own scripts makes it easier if you eventually want to contribute them to blender.
|
||||
This style guide is known as `pep8 <https://www.python.org/dev/peps/pep-0008/>`__
|
||||
and here is a brief listing of pep8 criteria:
|
||||
|
||||
This style guide is known as pep8 and can be found `here <https://www.python.org/dev/peps/pep-0008/>`_
|
||||
- Camel caps for class names: MyClass
|
||||
- All lower case underscore separated module names: my_module
|
||||
- Indentation of 4 spaces (no tabs)
|
||||
- Spaces around operators: ``1 + 1``, not ``1+1``
|
||||
- Only use explicit imports (no wildcard importing ``*``)
|
||||
- Don't use multiple statements on a single line: ``if val: body``, separate onto two lines instead.
|
||||
|
||||
A brief listing of pep8 criteria.
|
||||
|
||||
- camel caps for class names: MyClass
|
||||
- all lower case underscore separated module names: my_module
|
||||
- indentation of 4 spaces (no tabs)
|
||||
- spaces around operators. ``1 + 1``, not ``1+1``
|
||||
- only use explicit imports, (no importing ``*``)
|
||||
- don't use single line: ``if val: body``, separate onto 2 lines instead.
|
||||
|
||||
|
||||
As well as pep8 we have other conventions used for blender python scripts.
|
||||
As well as pep8 we have additional conventions used for Blender Python scripts:
|
||||
|
||||
- Use single quotes for enums, and double quotes for strings.
|
||||
|
||||
Both are of course strings, but in our internal API enums are unique items from a limited set. eg.
|
||||
Both are of course strings, but in our internal API enums are unique items from a limited set, e.g:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -42,14 +38,14 @@ As well as pep8 we have other conventions used for blender python scripts.
|
||||
bpy.context.scene.render.filepath = "//render_out"
|
||||
|
||||
- pep8 also defines that lines should not exceed 79 characters,
|
||||
we felt this is too restrictive so this is optional per script.
|
||||
we have decided that this is too restrictive so it is optional per script.
|
||||
|
||||
Periodically we run checks for pep8 compliance on blender scripts,
|
||||
for scripts to be included in this check add this line as a comment at the top of the script.
|
||||
Periodically we run checks for pep8 compliance on Blender scripts,
|
||||
for scripts to be included in this check add this line as a comment at the top of the script:
|
||||
|
||||
``# <pep8 compliant>``
|
||||
|
||||
To enable line length checks use this instead.
|
||||
To enable line length checks use this instead:
|
||||
|
||||
``# <pep8-80 compliant>``
|
||||
|
||||
@@ -59,85 +55,79 @@ User Interface Layout
|
||||
|
||||
Some notes to keep in mind when writing UI layouts:
|
||||
|
||||
- UI code is quite simple. Layout declarations are there to easily create a decent layout.
|
||||
UI code is quite simple. Layout declarations are there to easily create a decent layout.
|
||||
The general rule here is: If you need more code for the layout declaration,
|
||||
than for the actual properties, then you are doing it wrong.
|
||||
|
||||
General rule here: If you need more code for the layout declaration,
|
||||
then for the actual properties, you do it wrong.
|
||||
|
||||
Example layouts:
|
||||
.. rubric:: Example layouts:
|
||||
|
||||
- layout()
|
||||
``layout()``
|
||||
The basic layout is a simple top-to-bottom layout.
|
||||
|
||||
The basic layout is a simple Top -> Bottom layout.
|
||||
.. code-block:: python
|
||||
|
||||
.. code-block:: python
|
||||
layout.prop()
|
||||
layout.prop()
|
||||
|
||||
layout.prop()
|
||||
layout.prop()
|
||||
``layout.row()``
|
||||
Use ``row()``, when you want more than one property in a single line.
|
||||
|
||||
- layout.row()
|
||||
.. code-block:: python
|
||||
|
||||
Use row(), when you want more than 1 property in one line.
|
||||
row = layout.row()
|
||||
row.prop()
|
||||
row.prop()
|
||||
|
||||
.. code-block:: python
|
||||
``layout.column()``
|
||||
Use ``column()``, when you want your properties in a column.
|
||||
|
||||
row = layout.row()
|
||||
row.prop()
|
||||
row.prop()
|
||||
.. code-block:: python
|
||||
|
||||
- layout.column()
|
||||
col = layout.column()
|
||||
col.prop()
|
||||
col.prop()
|
||||
|
||||
Use column(), when you want your properties in a column.
|
||||
``layout.split()``
|
||||
This can be used to create more complex layouts.
|
||||
For example, you can split the layout and create two ``column()`` layouts next to each other.
|
||||
Do not use split, when you simply want two properties in a row. Use ``row()`` instead.
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
col = layout.column()
|
||||
col.prop()
|
||||
col.prop()
|
||||
split = layout.split()
|
||||
|
||||
- layout.split()
|
||||
col = split.column()
|
||||
col.prop()
|
||||
col.prop()
|
||||
|
||||
This can be used to create more complex layouts.
|
||||
For example you can split the layout and create two column() layouts next to each other.
|
||||
Don't use split, when you simply want two properties in a row. Use row() for that.
|
||||
col = split.column()
|
||||
col.prop()
|
||||
col.prop()
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
col.prop()
|
||||
col.prop()
|
||||
|
||||
col = split.column()
|
||||
col.prop()
|
||||
col.prop()
|
||||
|
||||
Declaration names:
|
||||
.. rubric:: Declaration names:
|
||||
|
||||
Try to only use these variable names for layout declarations:
|
||||
|
||||
- row for a row() layout
|
||||
- col for a column() layout
|
||||
- split for a split() layout
|
||||
- flow for a column_flow() layout
|
||||
- sub for a sub layout (a column inside a column for example)
|
||||
:row: for a ``row()`` layout
|
||||
:col: for a ``column()`` layout
|
||||
:split: for a ``split()`` layout
|
||||
:flow: for a ``column_flow()`` layout
|
||||
:sub: for a sub layout (a column inside a column for example)
|
||||
|
||||
|
||||
Script Efficiency
|
||||
=================
|
||||
|
||||
|
||||
List Manipulation (General Python Tips)
|
||||
---------------------------------------
|
||||
|
||||
|
||||
Searching for list items
|
||||
Searching for List Items
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In Python there are some handy list functions that save you having to search through the list.
|
||||
|
||||
Even though you are not looping on the list data **python is**,
|
||||
Even though you are not looping on the list data **Python is**,
|
||||
so you need to be aware of functions that will slow down your script by searching the whole list.
|
||||
|
||||
.. code-block:: python
|
||||
@@ -150,23 +140,21 @@ so you need to be aware of functions that will slow down your script by searchin
|
||||
|
||||
Modifying Lists
|
||||
^^^^^^^^^^^^^^^
|
||||
In python we can add and remove from a list, this is slower when the list length is modified,
|
||||
especially at the start of the list, since all the data after the index of
|
||||
modification needs to be moved up or down 1 place.
|
||||
|
||||
The most simple way to add onto the end of the list is to use
|
||||
``my_list.append(list_item)`` or ``my_list.extend(some_list)`` and the fastest way to
|
||||
remove an item is ``my_list.pop()`` or ``del my_list[-1]``.
|
||||
In Python you can add and remove from a list, this is slower when the list length is modified,
|
||||
especially at the start of the list, since all the data after the index of
|
||||
modification needs to be moved up or down one place.
|
||||
|
||||
The fastest way to add onto the end of the list is to use
|
||||
``my_list.append(list_item)`` or ``my_list.extend(some_list)`` and
|
||||
to remove an item is ``my_list.pop()`` or ``del my_list[-1]``.
|
||||
|
||||
To use an index you can use ``my_list.insert(index, list_item)`` or ``list.pop(index)``
|
||||
for list removal, but these are slower.
|
||||
|
||||
Sometimes its faster (but more memory hungry) to just rebuild the list.
|
||||
|
||||
|
||||
Say you want to remove all triangular polygons in a list.
|
||||
|
||||
Rather than...
|
||||
Sometimes it's faster (but less memory efficient) to just rebuild the list.
|
||||
For example if you want to remove all triangular polygons in a list.
|
||||
Rather than:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -179,7 +167,7 @@ Rather than...
|
||||
polygons.pop(p_idx) # remove the triangle
|
||||
|
||||
|
||||
It's faster to build a new list with list comprehension.
|
||||
It's faster to build a new list with list comprehension:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -189,14 +177,14 @@ It's faster to build a new list with list comprehension.
|
||||
Adding List Items
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you have a list that you want to add onto another list, rather than...
|
||||
If you have a list that you want to add onto another list, rather than:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
for l in some_list:
|
||||
my_list.append(l)
|
||||
|
||||
Use...
|
||||
Use:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -205,9 +193,7 @@ Use...
|
||||
|
||||
Note that insert can be used when needed,
|
||||
but it is slower than append especially when inserting at the start of a long list.
|
||||
|
||||
This example shows a very sub-optimal way of making a reversed list.
|
||||
|
||||
This example shows a very suboptimal way of making a reversed list:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -219,7 +205,6 @@ This example shows a very sub-optimal way of making a reversed list.
|
||||
Python provides more convenient ways to reverse a list using the slice method,
|
||||
but you may want to time this before relying on it too much:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
some_reversed_list = some_list[::-1]
|
||||
@@ -228,12 +213,10 @@ but you may want to time this before relying on it too much:
|
||||
Removing List Items
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Use ``my_list.pop(index)`` rather than ``my_list.remove(list_item)``
|
||||
|
||||
Use ``my_list.pop(index)`` rather than ``my_list.remove(list_item)``.
|
||||
This requires you to have the index of the list item but is faster since ``remove()`` will search the list.
|
||||
|
||||
Here is an example of how to remove items in 1 loop,
|
||||
removing the last items first, which is faster (as explained above).
|
||||
Here is an example of how to remove items in one loop,
|
||||
removing the last items first, which is faster (as explained above):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -247,7 +230,7 @@ removing the last items first, which is faster (as explained above).
|
||||
|
||||
This example shows a fast way of removing items,
|
||||
for use in cases where you can alter the list order without breaking the scripts functionality.
|
||||
This works by swapping 2 list items, so the item you remove is always last.
|
||||
This works by swapping two list items, so the item you remove is always last:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -260,64 +243,59 @@ This works by swapping 2 list items, so the item you remove is always last.
|
||||
my_list.pop()
|
||||
|
||||
|
||||
When removing many items in a large list this can provide a good speedup.
|
||||
When removing many items in a large list this can provide a good speed-up.
|
||||
|
||||
|
||||
Avoid Copying Lists
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When passing a list/dictionary to a function,
|
||||
When passing a list or dictionary to a function,
|
||||
it is faster to have the function modify the list rather than returning
|
||||
a new list so python doesn't have to duplicate the list in memory.
|
||||
a new list so Python doesn't have to duplicate the list in memory.
|
||||
|
||||
Functions that modify a list in-place are more efficient than functions that create new lists.
|
||||
|
||||
|
||||
This is generally slower so only use for functions when it makes sense not to modify the list in place.
|
||||
This is generally slower so only use for functions when it makes sense not to modify the list in place:
|
||||
|
||||
>>> my_list = some_list_func(my_list)
|
||||
|
||||
|
||||
This is generally faster since there is no re-assignment and no list duplication.
|
||||
This is generally faster since there is no re-assignment and no list duplication:
|
||||
|
||||
>>> some_list_func(vec)
|
||||
|
||||
|
||||
Also note that passing a sliced list makes a copy of the list in python memory.
|
||||
Also note that, passing a sliced list makes a copy of the list in Python memory:
|
||||
|
||||
>>> foobar(my_list[:])
|
||||
|
||||
If my_list was a large array containing 10000's of items, a copy could use a lot of extra memory.
|
||||
If my_list was a large array containing 10,000's of items, a copy could use a lot of extra memory.
|
||||
|
||||
|
||||
Writing Strings to a File (Python General)
|
||||
------------------------------------------
|
||||
|
||||
Here are 3 ways of joining multiple strings into one string for writing.
|
||||
This also applies to any area of your code that involves a lot of string joining.
|
||||
Here are three ways of joining multiple strings into one string for writing.
|
||||
This also applies to any area of your code that involves a lot of string joining:
|
||||
|
||||
String concatenation
|
||||
This is the slowest option, do **not** use if you can avoid it, especially when writing data in a loop.
|
||||
|
||||
>>> file.write(str1 + " " + str2 + " " + str3 + "\n")
|
||||
|
||||
String formatting
|
||||
Use this when you are writing string data from floats and ints.
|
||||
|
||||
>>> file.write("%s %s %s\n" % (str1, str2, str3))
|
||||
|
||||
String joining
|
||||
Use to join a list of strings (the list may be temporary). In the following example, the strings are joined with
|
||||
a space " " in between, other examples are "" or ", ".
|
||||
|
||||
>>> file.write(" ".join((str1, str2, str3, "\n")))
|
||||
|
||||
|
||||
``String addition`` -
|
||||
this is the slowest option, *don't use if you can help it, especially when writing data in a loop*.
|
||||
|
||||
>>> file.write(str1 + " " + str2 + " " + str3 + "\n")
|
||||
|
||||
|
||||
``String formatting`` -
|
||||
use this when you are writing string data from floats and ints.
|
||||
|
||||
>>> file.write("%s %s %s\n" % (str1, str2, str3))
|
||||
|
||||
|
||||
``String join() function``
|
||||
use to join a list of strings (the list may be temporary). In the following example, the strings are joined with a space " " in between, other examples are "" or ", ".
|
||||
|
||||
>>> file.write(" ".join([str1, str2, str3, "\n"]))
|
||||
|
||||
|
||||
Join is fastest on many strings,
|
||||
`string formatting <https://wiki.blender.org/index.php/Dev:Source/Modeling/BMesh/Design>`__
|
||||
is quite fast too (better for converting data types). String arithmetic is slowest.
|
||||
Join is fastest on many strings, string formatting is quite fast too (better for converting data types).
|
||||
String concatenation is the slowest.
|
||||
|
||||
|
||||
Parsing Strings (Import/Exporting)
|
||||
@@ -333,36 +311,35 @@ Parsing Numbers
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Use ``float(string)`` rather than ``eval(string)``, if you know the value will be an int then ``int(string)``,
|
||||
float() will work for an int too but it is faster to read ints with int().
|
||||
``float()`` will work for an int too but it is faster to read ints with ``int()``.
|
||||
|
||||
|
||||
Checking String Start/End
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you are checking the start of a string for a keyword, rather than...
|
||||
If you are checking the start of a string for a keyword, rather than:
|
||||
|
||||
>>> if line[0:5] == "vert ": ...
|
||||
|
||||
use...
|
||||
Use:
|
||||
|
||||
>>> if line.startswith("vert "):
|
||||
|
||||
Using ``startswith()`` is slightly faster (approx 5%) and also avoids a possible
|
||||
error with the slice length not matching the string length.
|
||||
Using ``startswith()`` is slightly faster (around 5%) and also avoids a possible error
|
||||
with the slice length not matching the string length.
|
||||
|
||||
my_string.endswith("foo_bar") can be used for line endings too.
|
||||
``my_string.endswith("foo_bar")`` can be used for line endings too.
|
||||
|
||||
If you are unsure whether the text is upper or lower case, use the ``lower()`` or ``upper()`` string function.
|
||||
If you are unsure whether the text is upper or lower case, use the ``lower()`` or ``upper()`` string function:
|
||||
|
||||
>>> if line.lower().startswith("vert ")
|
||||
|
||||
|
||||
Use try/except Sparingly
|
||||
------------------------
|
||||
Error Handling
|
||||
--------------
|
||||
|
||||
The **try** statement is useful to save time writing error checking code.
|
||||
|
||||
However **try** is significantly slower than an **if** since an exception has to be set each time,
|
||||
However, **try** is significantly slower than an **if** since an exception has to be set each time,
|
||||
so avoid using **try** in areas of your code that execute in a loop and runs many times.
|
||||
|
||||
There are cases where using **try** is faster than checking whether the condition will raise an error,
|
||||
@@ -382,7 +359,7 @@ In cases where you know you are checking for the same value which is referenced
|
||||
Time Your Code
|
||||
--------------
|
||||
|
||||
While developing a script it is good to time it to be aware of any changes in performance, this can be done simply.
|
||||
While developing a script it is good to time it to be aware of any changes in performance, this can be done simply:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@@ -4,7 +4,7 @@ Gotchas
|
||||
*******
|
||||
|
||||
This document attempts to help you work with the Blender API in areas
|
||||
that can be troublesome and avoid practices that are known to give instability.
|
||||
that can be troublesome and avoid practices that are known to cause instability.
|
||||
|
||||
|
||||
.. _using_operators:
|
||||
@@ -12,13 +12,13 @@ that can be troublesome and avoid practices that are known to give instability.
|
||||
Using Operators
|
||||
===============
|
||||
|
||||
Blender's operators are tools for users to access, that Python can access them too is very useful
|
||||
nevertheless operators have limitations that can make them cumbersome to script.
|
||||
Blender's operators are tools for users to access, that can access with Python too which is very useful.
|
||||
Still operators have limitations that can make them cumbersome to script.
|
||||
|
||||
Main limits are...
|
||||
The main limits are:
|
||||
|
||||
- Can't pass data such as objects, meshes or materials to operate on (operators use the context instead)
|
||||
- The return value from calling an operator gives the success (if it finished or was canceled),
|
||||
- Can't pass data such as objects, meshes or materials to operate on (operators use the context instead).
|
||||
- The return value from calling an operator is the success (if it finished or was canceled),
|
||||
in some cases it would be more logical from an API perspective to return the result of the operation.
|
||||
- Operators poll function can fail where an API function would raise an exception giving details on exactly why.
|
||||
|
||||
@@ -34,26 +34,23 @@ When calling an operator gives an error like this:
|
||||
Which raises the question as to what the correct context might be?
|
||||
|
||||
Typically operators check for the active area type, a selection or active object they can operate on,
|
||||
but some operators are more picky about when they run.
|
||||
|
||||
but some operators are more strict when they run.
|
||||
In most cases you can figure out what context an operator needs
|
||||
simply be seeing how it's used in Blender and thinking about what it does.
|
||||
|
||||
Unfortunately if you're still stuck - the only way to **really** know
|
||||
what's going on is to read the source code for the poll function and see what its checking.
|
||||
by examining how it's used in Blender and thinking about what it does.
|
||||
|
||||
If you're still stuck, unfortunately, the only way to eventually know what is causing the error is
|
||||
to read the source code for the poll function and see what it is checking.
|
||||
For Python operators it's not so hard to find the source
|
||||
since it's included with Blender and the source file/line is included in the operator reference docs.
|
||||
|
||||
since it's included with Blender and the source file and line is included in the operator reference docs.
|
||||
Downloading and searching the C code isn't so simple,
|
||||
especially if you're not familiar with the C language but by searching the
|
||||
operator name or description you should be able to find the poll function with no knowledge of C.
|
||||
especially if you're not familiar with the C language but by searching the operator name or description
|
||||
you should be able to find the poll function with no knowledge of C.
|
||||
|
||||
.. note::
|
||||
|
||||
Blender does have the functionality for poll functions to describe why they fail,
|
||||
but its currently not used much, if you're interested to help improve our API
|
||||
feel free to add calls to ``CTX_wm_operator_poll_msg_set`` where its not obvious why poll fails.
|
||||
but its currently not used much, if you're interested to help improve the API
|
||||
feel free to add calls to ``CTX_wm_operator_poll_msg_set`` where its not obvious why poll fails, e.g:
|
||||
|
||||
>>> bpy.ops.gpencil.draw()
|
||||
RuntimeError: Operator bpy.ops.gpencil.draw.poll() Failed to find Grease Pencil data to draw into
|
||||
@@ -63,7 +60,7 @@ The operator still doesn't work!
|
||||
--------------------------------
|
||||
|
||||
Certain operators in Blender are only intended for use in a specific context,
|
||||
some operators for example are only called from the properties window where they check the current material,
|
||||
some operators for example are only called from the properties editor where they check the current material,
|
||||
modifier or constraint.
|
||||
|
||||
Examples of this are:
|
||||
@@ -74,8 +71,8 @@ Examples of this are:
|
||||
- :mod:`bpy.ops.buttons.file_browse`
|
||||
|
||||
Another possibility is that you are the first person to attempt to use this operator
|
||||
in a script and some modifications need to be made to the operator to run in a different context,
|
||||
if the operator should logically be able to run but fails when accessed from a script
|
||||
in a script and some modifications need to be made to the operator to run in a different context.
|
||||
If the operator should logically be able to run but fails when accessed from a script
|
||||
it should be reported to the bug tracker.
|
||||
|
||||
|
||||
@@ -85,22 +82,20 @@ Stale Data
|
||||
No updates after setting values
|
||||
-------------------------------
|
||||
|
||||
Sometimes you want to modify values from Python and immediately access the updated values, eg:
|
||||
|
||||
Sometimes you want to modify values from Python and immediately access the updated values, e.g:
|
||||
Once changing the objects :class:`bpy.types.Object.location`
|
||||
you may want to access its transformation right after from :class:`bpy.types.Object.matrix_world`,
|
||||
but this doesn't work as you might expect.
|
||||
|
||||
Consider the calculations that might go into working out the object's final transformation, this includes:
|
||||
Consider the calculations that might contribute to the object's final transformation, this includes:
|
||||
|
||||
- animation function curves.
|
||||
- drivers and their Python expressions.
|
||||
- constraints
|
||||
- parent objects and all of their f-curves, constraints etc.
|
||||
- Animation function curves.
|
||||
- Drivers and their Python expressions.
|
||||
- Constraints
|
||||
- Parent objects and all of their F-curves, constraints, etc.
|
||||
|
||||
To avoid expensive recalculations every time a property is modified,
|
||||
Blender defers making the actual calculations until they are needed.
|
||||
|
||||
Blender defers the evaluation until the results are needed.
|
||||
However, while the script runs you may want to access the updated values.
|
||||
In this case you need to call :class:`bpy.types.ViewLayer.update` after modifying values, for example:
|
||||
|
||||
@@ -110,44 +105,41 @@ In this case you need to call :class:`bpy.types.ViewLayer.update` after modifyin
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
|
||||
Now all dependent data (child objects, modifiers, drivers... etc)
|
||||
Now all dependent data (child objects, modifiers, drivers, etc.)
|
||||
has been recalculated and is available to the script within active view layer.
|
||||
|
||||
|
||||
Can I redraw during the script?
|
||||
-------------------------------
|
||||
Can I redraw during script execution?
|
||||
-------------------------------------
|
||||
|
||||
The official answer to this is no, or... *"You don't want to do that"*.
|
||||
|
||||
To give some background on the topic...
|
||||
To give some background on the topic:
|
||||
|
||||
While a script executes Blender waits for it to finish and is effectively locked until its done,
|
||||
while in this state Blender won't redraw or respond to user input.
|
||||
Normally this is not such a problem because scripts distributed with Blender
|
||||
tend not to run for an extended period of time,
|
||||
nevertheless scripts *can* take ages to execute and its nice to see what's going on in the view port.
|
||||
nevertheless scripts *can* take a long time to complete and it would be nice to see progress in the viewport.
|
||||
|
||||
Tools that lock Blender in a loop and redraw are highly discouraged
|
||||
since they conflict with Blenders ability to run multiple operators
|
||||
When tools lock Blender in a loop redraw are highly discouraged
|
||||
since they conflict with Blender's ability to run multiple operators
|
||||
at once and update different parts of the interface as the tool runs.
|
||||
|
||||
So the solution here is to write a **modal** operator, that is - an operator which defines a modal() function,
|
||||
See the modal operator template in the text editor.
|
||||
|
||||
So the solution here is to write a **modal** operator, which is an operator that defines a ``modal()`` function,
|
||||
See the modal operator template in the text editor.
|
||||
Modal operators execute on user input or setup their own timers to run frequently,
|
||||
they can handle the events or pass through to be handled by the keymap or other modal operators.
|
||||
|
||||
Transform, Painting, Fly-Mode and File-Select are example of a modal operators.
|
||||
Examples of a modal operators are Transform, Painting, Fly Navigation and File Select.
|
||||
|
||||
Writing modal operators takes more effort than a simple ``for`` loop
|
||||
that happens to redraw but is more flexible and integrates better with Blenders design.
|
||||
that contains draw calls but is more flexible and integrates better with Blender's design.
|
||||
|
||||
|
||||
**Ok, Ok! I still want to draw from Python**
|
||||
.. rubric:: Ok, Ok! I still want to draw from Python
|
||||
|
||||
If you insist - yes its possible, but scripts that use this hack won't be considered
|
||||
for inclusion in Blender and any issues with using it won't be considered bugs,
|
||||
this is also not guaranteed to work in future releases.
|
||||
If you insist -- yes it's possible, but scripts that use this hack will not be considered
|
||||
for inclusion in Blender and any issue with using it will not be considered a bug,
|
||||
there is also no guaranteed compatibility in future releases.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -157,18 +149,18 @@ this is also not guaranteed to work in future releases.
|
||||
Modes and Mesh Access
|
||||
=====================
|
||||
|
||||
When working with mesh data you may run into the problem where a script fails to run as expected in edit-mode.
|
||||
This is caused by edit-mode having its own data which is only written back to the mesh when exiting edit-mode.
|
||||
When working with mesh data you may run into the problem where a script fails to run as expected in Edit-Mode.
|
||||
This is caused by Edit-Mode having its own data which is only written back to the mesh when exiting Edit-Mode.
|
||||
|
||||
A common example is that exporters may access a mesh through ``obj.data`` (a :class:`bpy.types.Mesh`)
|
||||
but the user is in edit-mode, where the mesh data is available but out of sync with the edit mesh.
|
||||
when the user is in Edit-Mode, where the mesh data is available but out of sync with the edit mesh.
|
||||
|
||||
In this situation you can...
|
||||
|
||||
- Exit edit-mode before running the tool.
|
||||
- Exit Edit-Mode before running the tool.
|
||||
- Explicitly update the mesh by calling :class:`bmesh.types.BMesh.to_mesh`.
|
||||
- Modify the script to support working on the edit-mode data directly, see: :mod:`bmesh.from_edit_mesh`.
|
||||
- Report the context as incorrect and only allow the script to run outside edit-mode.
|
||||
- Report the context as incorrect and only allow the script to run outside Edit-Mode.
|
||||
|
||||
|
||||
.. _info_gotcha_mesh_faces:
|
||||
@@ -176,24 +168,24 @@ In this situation you can...
|
||||
N-Gons and Tessellation
|
||||
=======================
|
||||
|
||||
Since 2.63 NGons are supported, this adds some complexity
|
||||
Since 2.63 n-gons are supported, this adds some complexity
|
||||
since in some cases you need to access triangles still (some exporters for example).
|
||||
|
||||
There are now 3 ways to access faces:
|
||||
There are now three ways to access faces:
|
||||
|
||||
- :class:`bpy.types.MeshPolygon` -
|
||||
this is the data structure which now stores faces in object mode
|
||||
- :class:`bpy.types.MeshPolygon` --
|
||||
this is the data structure which now stores faces in Object-Mode
|
||||
(access as ``mesh.polygons`` rather than ``mesh.faces``).
|
||||
- :class:`bpy.types.MeshLoopTriangle` -
|
||||
- :class:`bpy.types.MeshLoopTriangle` --
|
||||
the result of tessellating polygons into triangles
|
||||
(access as ``mesh.loop_triangles``).
|
||||
- :class:`bmesh.types.BMFace` -
|
||||
the polygons as used in editmode.
|
||||
- :class:`bmesh.types.BMFace` --
|
||||
the polygons as used in Edit-Mode.
|
||||
|
||||
For the purpose of the following documentation,
|
||||
these will be referred to as polygons, loop triangles and bmesh-faces respectively.
|
||||
these will be referred to as polygons, loop triangles and BMesh-faces respectively.
|
||||
|
||||
5+ sided faces will be referred to as ``ngons``.
|
||||
Faces with five or more sides will be referred to as ``ngons``.
|
||||
|
||||
|
||||
Support Overview
|
||||
@@ -216,58 +208,58 @@ Support Overview
|
||||
- Unusable *(read-only)*.
|
||||
- Best
|
||||
* - Export/Output
|
||||
- Good *(ngon support)*
|
||||
- Good *(When ngons can't be used)*
|
||||
- Good *(ngons, extra memory overhead)*
|
||||
- Good *(n-gon support)*
|
||||
- Good *(When n-gons cannot be used)*
|
||||
- Good *(n-gons, extra memory overhead)*
|
||||
|
||||
.. note::
|
||||
|
||||
Using the :mod:`bmesh` API is completely separate API from :mod:`bpy`,
|
||||
typically you would would use one or the other based on the level of editing needed,
|
||||
typically you would use one or the other based on the level of editing needed,
|
||||
not simply for a different way to access faces.
|
||||
|
||||
|
||||
Creating
|
||||
--------
|
||||
|
||||
All 3 datatypes can be used for face creation.
|
||||
All three data types can be used for face creation:
|
||||
|
||||
- polygons are the most efficient way to create faces but the data structure is _very_ rigid and inflexible,
|
||||
- Polygons are the most efficient way to create faces but the data structure is *very* rigid and inflexible,
|
||||
you must have all your vertices and faces ready and create them all at once.
|
||||
This is further complicated by the fact that each polygon does not store its own verts,
|
||||
This is further complicated by the fact that each polygon does not store its own vertices,
|
||||
rather they reference an index and size in :class:`bpy.types.Mesh.loops` which are a fixed array too.
|
||||
- bmesh-faces are most likely the easiest way for new scripts to create faces,
|
||||
since faces can be added one by one and the api has features intended for mesh manipulation.
|
||||
- BMesh-faces are most likely the easiest way to create faces in new scripts,
|
||||
since faces can be added one by one and the API has features intended for mesh manipulation.
|
||||
While :class:`bmesh.types.BMesh` uses more memory it can be managed by only operating on one mesh at a time.
|
||||
|
||||
|
||||
Editing
|
||||
-------
|
||||
|
||||
Editing is where the 3 data types vary most.
|
||||
Editing is where the three data types vary most.
|
||||
|
||||
- Polygons are very limited for editing,
|
||||
changing materials and options like smooth works but for anything else
|
||||
they are too inflexible and are only intended for storage.
|
||||
- Tessfaces should not be used for editing geometry because doing so will cause existing ngons to be tessellated.
|
||||
- BMesh-Faces are by far the best way to manipulate geometry.
|
||||
- Tessfaces should not be used for editing geometry because doing so will cause existing n-gons to be tessellated.
|
||||
- BMesh-faces are by far the best way to manipulate geometry.
|
||||
|
||||
|
||||
Exporting
|
||||
---------
|
||||
|
||||
All 3 data types can be used for exporting,
|
||||
the choice mostly depends on whether the target format supports ngons or not.
|
||||
All three data types can be used for exporting,
|
||||
the choice mostly depends on whether the target format supports n-gons or not.
|
||||
|
||||
- Polygons are the most direct & efficient way to export providing they convert into the output format easily enough.
|
||||
- Tessfaces work well for exporting to formats which don't support ngons,
|
||||
- Polygons are the most direct and efficient way to export providing they convert into the output format easily enough.
|
||||
- Tessfaces work well for exporting to formats which don't support n-gons,
|
||||
in fact this is the only place where their use is encouraged.
|
||||
- BMesh-Faces can work for exporting too but may not be necessary if polygons can be used
|
||||
since using bmesh gives some overhead because its not the native storage format in object mode.
|
||||
since using BMesh gives some overhead because its not the native storage format in Object-Mode.
|
||||
|
||||
|
||||
EditBones, PoseBones, Bone... Bones
|
||||
===================================
|
||||
Edit Bones, Pose Bones, Bone... Bones
|
||||
=====================================
|
||||
|
||||
Armature Bones in Blender have three distinct data structures that contain them.
|
||||
If you are accessing the bones through one of them, you may not have access to the properties you really need.
|
||||
@@ -280,43 +272,41 @@ If you are accessing the bones through one of them, you may not have access to t
|
||||
Edit Bones
|
||||
----------
|
||||
|
||||
``bpy.context.object.data.edit_bones`` contains a editbones;
|
||||
to access them you must set the armature mode to edit mode first (editbones do not exist in object or pose mode).
|
||||
``bpy.context.object.data.edit_bones`` contains an edit bones;
|
||||
to access them you must set the armature mode to Edit-Mode first (edit bones do not exist in Object or Pose-Mode).
|
||||
Use these to create new bones, set their head/tail or roll, change their parenting relationships to other bones, etc.
|
||||
|
||||
Example using :class:`bpy.types.EditBone` in armature editmode:
|
||||
|
||||
This is only possible in edit mode.
|
||||
Example using :class:`bpy.types.EditBone` in armature Edit-Mode
|
||||
which is only possible in Edit-Mode:
|
||||
|
||||
>>> bpy.context.object.data.edit_bones["Bone"].head = Vector((1.0, 2.0, 3.0))
|
||||
|
||||
This will be empty outside of editmode.
|
||||
This will be empty outside of Edit-Mode:
|
||||
|
||||
>>> mybones = bpy.context.selected_editable_bones
|
||||
|
||||
Returns an editbone only in edit mode.
|
||||
Returns an edit bone only in Edit-Mode:
|
||||
|
||||
>>> bpy.context.active_bone
|
||||
|
||||
|
||||
Bones (Object Mode)
|
||||
Bones (Object-Mode)
|
||||
-------------------
|
||||
|
||||
``bpy.context.object.data.bones`` contains bones.
|
||||
These *live* in object mode, and have various properties you can change,
|
||||
These *live* in Object-Mode, and have various properties you can change,
|
||||
note that the head and tail properties are read-only.
|
||||
|
||||
Example using :class:`bpy.types.Bone` in object or pose mode:
|
||||
|
||||
Returns a bone (not an editbone) outside of edit mode
|
||||
Example using :class:`bpy.types.Bone` in Object or Pose-Mode
|
||||
returning a bone (not an edit bone) outside of Edit-Mode:
|
||||
|
||||
>>> bpy.context.active_bone
|
||||
|
||||
This works, as with blender the setting can be edited in any mode
|
||||
This works, as with Blender the setting can be edited in any mode:
|
||||
|
||||
>>> bpy.context.object.data.bones["Bone"].use_deform = True
|
||||
|
||||
Accessible but read-only
|
||||
Accessible but read-only:
|
||||
|
||||
>>> tail = myobj.data.bones["Bone"].tail
|
||||
|
||||
@@ -326,42 +316,42 @@ Pose Bones
|
||||
|
||||
``bpy.context.object.pose.bones`` contains pose bones.
|
||||
This is where animation data resides, i.e. animatable transformations
|
||||
are applied to pose bones, as are constraints and ik-settings.
|
||||
are applied to pose bones, as are constraints and IK-settings.
|
||||
|
||||
Examples using :class:`bpy.types.PoseBone` in object or pose mode:
|
||||
Examples using :class:`bpy.types.PoseBone` in Object or Pose-Mode:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Gets the name of the first constraint (if it exists)
|
||||
bpy.context.object.pose.bones["Bone"].constraints[0].name
|
||||
|
||||
# Gets the last selected pose bone (pose mode only)
|
||||
# Gets the last selected pose bone (Pose-Mode only)
|
||||
bpy.context.active_pose_bone
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Notice the pose is accessed from the object rather than the object data,
|
||||
this is why blender can have 2 or more objects sharing the same armature in different poses.
|
||||
this is why Blender can have two or more objects sharing the same armature in different poses.
|
||||
|
||||
.. note::
|
||||
|
||||
Strictly speaking PoseBone's are not bones, they are just the state of the armature,
|
||||
Strictly speaking pose bones are not bones, they are just the state of the armature,
|
||||
stored in the :class:`bpy.types.Object` rather than the :class:`bpy.types.Armature`,
|
||||
the real bones are however accessible from the pose bones - :class:`bpy.types.PoseBone.bone`
|
||||
yet the real bones are accessible from the pose bones via :class:`bpy.types.PoseBone.bone`.
|
||||
|
||||
|
||||
Armature Mode Switching
|
||||
-----------------------
|
||||
|
||||
While writing scripts that deal with armatures you may find you have to switch between modes,
|
||||
when doing so take care when switching out of edit-mode not to keep references
|
||||
to the edit-bones or their head/tail vectors.
|
||||
Further access to these will crash blender so its important the script
|
||||
when doing so take care when switching out of Edit-Mode not to keep references
|
||||
to the edit bones or their head/tail vectors.
|
||||
Further access to these will crash Blender so its important the script
|
||||
clearly separates sections of the code which operate in different modes.
|
||||
|
||||
This is mainly an issue with editmode since pose data can be manipulated without having to be in pose mode,
|
||||
however for operator access you may still need to enter pose mode.
|
||||
This is mainly an issue with Edit-Mode since pose data can be manipulated without having to be in Pose-Mode,
|
||||
yet for operator access you may still need to enter Pose-Mode.
|
||||
|
||||
|
||||
Data Names
|
||||
@@ -372,8 +362,7 @@ Naming Limitations
|
||||
------------------
|
||||
|
||||
A common mistake is to assume newly created data is given the requested name.
|
||||
|
||||
This can cause bugs when you add some data (normally imported) then reference it later by name.
|
||||
This can cause bugs when you add data (normally imported) then reference it later by name:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -383,7 +372,7 @@ This can cause bugs when you add some data (normally imported) then reference it
|
||||
bpy.data.meshes[meshid]
|
||||
|
||||
|
||||
Or with name assignment...
|
||||
Or with name assignment:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -397,12 +386,12 @@ Data names may not match the assigned values if they exceed the maximum length,
|
||||
|
||||
|
||||
Its better practice not to reference objects by names at all,
|
||||
once created you can store the data in a list, dictionary, on a class etc,
|
||||
once created you can store the data in a list, dictionary, on a class, etc;
|
||||
there is rarely a reason to have to keep searching for the same data by name.
|
||||
|
||||
If you do need to use name references, its best to use a dictionary to maintain
|
||||
a mapping between the names of the imported assets and the newly created data,
|
||||
this way you don't run this risk of referencing existing data from the blend file, or worse modifying it.
|
||||
this way you don't run this risk of referencing existing data from the blend-file, or worse modifying it.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -421,17 +410,14 @@ this way you don't run this risk of referencing existing data from the blend fil
|
||||
Library Collisions
|
||||
------------------
|
||||
|
||||
Blender keeps data names unique - :class:`bpy.types.ID.name` so you can't name two objects,
|
||||
meshes, scenes etc the same thing by accident.
|
||||
|
||||
However when linking in library data from another blend file naming collisions can occur,
|
||||
Blender keeps data names unique (:class:`bpy.types.ID.name`) so you can't name two objects,
|
||||
meshes, scenes, etc., the same by accident.
|
||||
However, when linking in library data from another blend-file naming collisions can occur,
|
||||
so its best to avoid referencing data by name at all.
|
||||
|
||||
This can be tricky at times and not even blender handles this correctly in some case
|
||||
(when selecting the modifier object for eg you can't select between multiple objects with the same name),
|
||||
but its still good to try avoid problems in this area.
|
||||
|
||||
|
||||
This can be tricky at times and not even Blender handles this correctly in some case
|
||||
(when selecting the modifier object for e.g. you can't select between multiple objects with the same name),
|
||||
but its still good to try avoiding these problems in this area.
|
||||
If you need to select between local and library data, there is a feature in ``bpy.data`` members to allow for this.
|
||||
|
||||
.. code-block:: python
|
||||
@@ -454,18 +440,17 @@ If you need to select between local and library data, there is a feature in ``bp
|
||||
Relative File Paths
|
||||
===================
|
||||
|
||||
Blenders relative file paths are not compatible with standard Python modules such as ``sys`` and ``os``.
|
||||
Blender's relative file paths are not compatible with standard Python modules such as ``sys`` and ``os``.
|
||||
Built-in Python functions don't understand Blender's ``//`` prefix which denotes the blend-file path.
|
||||
|
||||
Built in Python functions don't understand blenders ``//`` prefix which denotes the blend file path.
|
||||
|
||||
A common case where you would run into this problem is when exporting a material with associated image paths.
|
||||
A common case where you would run into this problem is when exporting a material with associated image paths:
|
||||
|
||||
>>> bpy.path.abspath(image.filepath)
|
||||
|
||||
|
||||
When using blender data from linked libraries there is an unfortunate complication
|
||||
since the path will be relative to the library rather than the open blend file.
|
||||
When the data block may be from an external blend file pass the library argument from the :class:`bpy.types.ID`.
|
||||
When using Blender data from linked libraries there is an unfortunate complication
|
||||
since the path will be relative to the library rather than the open blend-file.
|
||||
When the data block may be from an external blend-file pass the library argument from the :class:`bpy.types.ID`.
|
||||
|
||||
>>> bpy.path.abspath(image.filepath, library=image.library)
|
||||
|
||||
@@ -478,19 +463,15 @@ Unicode Problems
|
||||
|
||||
Python supports many different encodings so there is nothing stopping you from
|
||||
writing a script in ``latin1`` or ``iso-8859-15``.
|
||||
See `PEP 263 <https://www.python.org/dev/peps/pep-0263/>`__.
|
||||
|
||||
See `pep-0263 <https://www.python.org/dev/peps/pep-0263/>`_
|
||||
|
||||
However this complicates matters for Blender's Python API because ``.blend`` files don't have an explicit encoding.
|
||||
|
||||
To avoid the problem for Python integration and script authors we have decided all strings in blend files
|
||||
However, this complicates matters for Blender's Python API because ``.blend`` files don't have an explicit encoding.
|
||||
To avoid the problem for Python integration and script authors we have decided all strings in blend-files
|
||||
**must** be ``UTF-8``, ``ASCII`` compatible.
|
||||
|
||||
This means assigning strings with different encodings to an object names for instance will raise an error.
|
||||
|
||||
Paths are an exception to this rule since we cannot ignore the existence of non ``UTF-8`` paths on users file-system.
|
||||
|
||||
This means seemingly harmless expressions can raise errors, eg.
|
||||
Paths are an exception to this rule since the existence of non-UTF-8 paths on user's file system cannot be ignored.
|
||||
This means seemingly harmless expressions can raise errors, e.g:
|
||||
|
||||
>>> print(bpy.data.filepath)
|
||||
UnicodeEncodeError: 'ascii' codec can't encode characters in position 10-21: ordinal not in range(128)
|
||||
@@ -501,7 +482,7 @@ This means seemingly harmless expressions can raise errors, eg.
|
||||
TypeError: bpy_struct: item.attr= val: Object.name expected a string type, not str
|
||||
|
||||
|
||||
Here are 2 ways around filesystem encoding issues:
|
||||
Here are two ways around file-system encoding issues:
|
||||
|
||||
>>> print(repr(bpy.data.filepath))
|
||||
|
||||
@@ -512,11 +493,11 @@ Here are 2 ways around filesystem encoding issues:
|
||||
|
||||
|
||||
Unicode encoding/decoding is a big topic with comprehensive Python documentation,
|
||||
to avoid getting stuck too deep in encoding problems - here are some suggestions:
|
||||
to keep it short about encoding problems -- here are some suggestions:
|
||||
|
||||
- Always use utf-8 encoding or convert to utf-8 where the input is unknown.
|
||||
- Avoid manipulating filepaths as strings directly, use ``os.path`` functions instead.
|
||||
- Use ``os.fsencode()`` / ``os.fsdecode()`` instead of built in string decoding functions when operating on paths.
|
||||
- Always use UTF-8 encoding or convert to UTF-8 where the input is unknown.
|
||||
- Avoid manipulating file paths as strings directly, use ``os.path`` functions instead.
|
||||
- Use ``os.fsencode()`` or ``os.fsdecode()`` instead of built-in string decoding functions when operating on paths.
|
||||
- To print paths or to include them in the user interface use ``repr(path)`` first
|
||||
or ``"%r" % path`` with string formatting.
|
||||
|
||||
@@ -528,11 +509,11 @@ to avoid getting stuck too deep in encoding problems - here are some suggestions
|
||||
some importers do this.
|
||||
|
||||
|
||||
Strange errors using 'threading' module
|
||||
=======================================
|
||||
Strange Errors when Using the 'Threading' Module
|
||||
================================================
|
||||
|
||||
Python threading with Blender only works properly when the threads finish up before the script does.
|
||||
By using ``threading.join()`` for example.
|
||||
Python threading with Blender only works properly when the threads finish up before the script does,
|
||||
for example by using ``threading.join()``.
|
||||
|
||||
Here is an example of threading supported by Blender:
|
||||
|
||||
@@ -571,8 +552,8 @@ Here is an example of threading supported by Blender:
|
||||
t.join()
|
||||
|
||||
|
||||
This an example of a timer which runs many times a second and moves
|
||||
the default cube continuously while Blender runs **(Unsupported)**.
|
||||
This an example of a timer which runs many times a second
|
||||
and moves the default cube continuously while Blender runs **(Unsupported)**.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -592,33 +573,33 @@ the default cube continuously while Blender runs **(Unsupported)**.
|
||||
Use cases like the one above which leave the thread running once the script finishes
|
||||
may seem to work for a while but end up causing random crashes or errors in Blender's own drawing code.
|
||||
|
||||
So far, no work has gone into making Blender's Python integration thread safe,
|
||||
so until its properly supported, best not make use of this.
|
||||
So far, no work has been done to make Blender's Python integration thread safe,
|
||||
so until it's properly supported, it's best not make use of this.
|
||||
|
||||
.. note::
|
||||
|
||||
Pythons threads only allow co-currency and won't speed up your scripts on multi-processor systems,
|
||||
the ``subprocess`` and ``multiprocess`` modules can be used with Blender and make use of multiple CPU's too.
|
||||
Python threads only allow concurrency and won't speed up your scripts on multiprocessor systems,
|
||||
the ``subprocess`` and ``multiprocess`` modules can be used with Blender to make use of multiple CPUs too.
|
||||
|
||||
|
||||
Help! My script crashes Blender
|
||||
===============================
|
||||
|
||||
**TL;DR:** Do not keep direct references to Blender data (of any kind) when modifying the container
|
||||
of that data, and/or when some undo/redo may happen (e.g. during modal operators execution...).
|
||||
:abbr:`TL;DR (Too long; didn't read.)` Do not keep direct references to Blender data (of any kind)
|
||||
when modifying the container of that data, and/or when some undo/redo may happen
|
||||
(e.g. during modal operators execution...).
|
||||
Instead, use indices (or other data always stored by value in Python, like string keys...),
|
||||
that allow you to get access to the desired data.
|
||||
|
||||
Ideally it would be impossible to crash Blender from Python
|
||||
however there are some problems with the API where it can be made to crash.
|
||||
|
||||
Ideally it would be impossible to crash Blender from Python,
|
||||
however, there are some problems with the API where it can be made to crash.
|
||||
Strictly speaking this is a bug in the API but fixing it would mean adding memory verification
|
||||
on every access since most crashes are caused by the Python objects referencing Blenders memory directly,
|
||||
on every access since most crashes are caused by the Python objects referencing Blender's memory directly,
|
||||
whenever the memory is freed or re-allocated, further Python access to it can crash the script.
|
||||
But fixing this would make the scripts run very slow,
|
||||
or writing a very different kind of API which doesn't reference the memory directly.
|
||||
|
||||
Here are some general hints to avoid running into these problems.
|
||||
Here are some general hints to avoid running into these problems:
|
||||
|
||||
- Be aware of memory limits,
|
||||
especially when working with large lists since Blender can crash simply by running out of memory.
|
||||
@@ -631,16 +612,16 @@ Here are some general hints to avoid running into these problems.
|
||||
- Modules or classes that remain active while Blender is used,
|
||||
should not hold references to data the user may remove, instead,
|
||||
fetch data from the context each time the script is activated.
|
||||
- Crashes may not happen every time, they may happen more on some configurations/operating-systems.
|
||||
- Be wary of recursive patterns, those are very efficient at hiding the issues described here.
|
||||
- See last sub-section about `Unfortunate Corner Cases`_ for some known breaking exceptions.
|
||||
- Crashes may not happen every time, they may happen more on some configurations or operating systems.
|
||||
- Be careful with recursive patterns, those are very efficient at hiding the issues described here.
|
||||
- See last subsection about `Unfortunate Corner Cases`_ for some known breaking exceptions.
|
||||
|
||||
.. note::
|
||||
|
||||
To find the line of your script that crashes you can use the ``faulthandler`` module.
|
||||
See the `faulthandler docs <https://docs.python.org/dev/library/faulthandler.html>`_.
|
||||
See the `Faulthandler docs <https://docs.python.org/dev/library/faulthandler.html>`__.
|
||||
|
||||
While the crash may be in Blenders C/C++ code,
|
||||
While the crash may be in Blender's C/C++ code,
|
||||
this can help a lot to track down the area of the script that causes the crash.
|
||||
|
||||
.. note::
|
||||
@@ -654,7 +635,7 @@ Here are some general hints to avoid running into these problems.
|
||||
in any possible way.
|
||||
|
||||
|
||||
**Don’t:**
|
||||
.. rubric:: Do not:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -673,7 +654,7 @@ Here are some general hints to avoid running into these problems.
|
||||
first_item.name = "foobar"
|
||||
|
||||
|
||||
**Do:**
|
||||
.. rubric:: Do:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -696,33 +677,31 @@ Here are some general hints to avoid running into these problems.
|
||||
Undo/Redo
|
||||
---------
|
||||
|
||||
Undo invalidates all :class:`bpy.types.ID` instances (Object, Scene, Mesh, Lamp... etc).
|
||||
Undo invalidates all :class:`bpy.types.ID` instances (Object, Scene, Mesh, Light, etc.).
|
||||
|
||||
This example shows how you can tell undo changes the memory locations.
|
||||
This example shows how you can tell undo changes the memory locations:
|
||||
|
||||
>>> hash(bpy.context.object)
|
||||
-9223372036849950810
|
||||
>>> hash(bpy.context.object)
|
||||
-9223372036849950810
|
||||
|
||||
# ... move the active object, then undo
|
||||
Move the active object, then undo:
|
||||
|
||||
>>> hash(bpy.context.object)
|
||||
-9223372036849951740
|
||||
|
||||
As suggested above, simply not holding references to data when Blender is used
|
||||
interactively by the user is the only way to ensure the script doesn't become unstable.
|
||||
interactively by the user is the only way to make sure that the script doesn't become unstable.
|
||||
|
||||
|
||||
Undo & Library Data
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
One of the advantages with Blenders library linking system that undo
|
||||
One of the advantages with Blender's library linking system that undo
|
||||
can skip checking changes in library data since it is assumed to be static.
|
||||
|
||||
Tools in Blender are not allowed to modify library data.
|
||||
|
||||
Python however does not enforce this restriction.
|
||||
But Python does not enforce this restriction.
|
||||
|
||||
This can be useful in some cases, using a script to adjust material values for example.
|
||||
But its also possible to use a script to make library data point to newly created local data,
|
||||
@@ -733,13 +712,13 @@ So it's best to consider modifying library data an advanced usage of the API
|
||||
and only to use it when you know what you're doing.
|
||||
|
||||
|
||||
Edit Mode / Memory Access
|
||||
Edit-Mode / Memory Access
|
||||
-------------------------
|
||||
|
||||
Switching edit-mode ``bpy.ops.object.mode_set(mode='EDIT')`` / ``bpy.ops.object.mode_set(mode='OBJECT')``
|
||||
Switching mode ``bpy.ops.object.mode_set(mode='EDIT')`` or ``bpy.ops.object.mode_set(mode='OBJECT')``
|
||||
will re-allocate objects data,
|
||||
any references to a meshes vertices/polygons/uvs, armatures bones,
|
||||
curves points etc cannot be accessed after switching edit-mode.
|
||||
any references to a meshes vertices/polygons/UVs, armatures bones,
|
||||
curves points, etc. cannot be accessed after switching mode.
|
||||
|
||||
Only the reference to the data its self can be re-accessed, the following example will crash.
|
||||
|
||||
@@ -754,7 +733,7 @@ Only the reference to the data its self can be re-accessed, the following exampl
|
||||
print(polygons)
|
||||
|
||||
|
||||
So after switching edit-mode you need to re-access any object data variables,
|
||||
So after switching mode you need to re-access any object data variables,
|
||||
the following example shows how to avoid the crash above.
|
||||
|
||||
.. code-block:: python
|
||||
@@ -770,7 +749,7 @@ the following example shows how to avoid the crash above.
|
||||
|
||||
|
||||
These kinds of problems can happen for any functions which re-allocate
|
||||
the object data but are most common when switching edit-mode.
|
||||
the object data but are most common when switching mode.
|
||||
|
||||
|
||||
Array Re-Allocation
|
||||
@@ -791,21 +770,20 @@ internally the array which stores this data is re-allocated.
|
||||
This can be avoided by re-assigning the point variables after adding the new one or by storing
|
||||
indices to the points rather than the points themselves.
|
||||
|
||||
The best way is to sidestep the problem altogether add all the points to the curve at once.
|
||||
This means you don't have to worry about array re-allocation and its faster too
|
||||
since reallocating the entire array for every point added is inefficient.
|
||||
The best way is to sidestep the problem altogether by adding all the points to the curve at once.
|
||||
This means you don't have to worry about array re-allocation and it's faster too
|
||||
since re-allocating the entire array for every added point is inefficient.
|
||||
|
||||
|
||||
Removing Data
|
||||
-------------
|
||||
|
||||
**Any** data that you remove shouldn't be modified or accessed afterwards,
|
||||
this includes f-curves, drivers, render layers, timeline markers, modifiers, constraints
|
||||
along with objects, scenes, collections, bones.. etc.
|
||||
this includes: F-curves, drivers, render layers, timeline markers, modifiers, constraints
|
||||
along with objects, scenes, collections, bones, etc.
|
||||
|
||||
The ``remove()`` api calls will invalidate the data they free to prevent common mistakes.
|
||||
|
||||
The following example shows how this precaution works.
|
||||
The ``remove()`` API calls will invalidate the data they free to prevent common mistakes.
|
||||
The following example shows how this precaution works:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -818,7 +796,7 @@ The following example shows how this precaution works.
|
||||
|
||||
|
||||
But take care because this is limited to scripts accessing the variable which is removed,
|
||||
the next example will still crash.
|
||||
the next example will still crash:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -835,8 +813,8 @@ Besides all expected cases listed above, there are a few others that should not
|
||||
an issue but, due to internal implementation details, currently are:
|
||||
|
||||
- ``Object.hide_viewport``, ``Object.hide_select`` and ``Object.hide_render``:
|
||||
Setting any of those booleans will trigger a rebuild of Collection caches, hence breaking
|
||||
any current iteration over ``Collection.all_objects``.
|
||||
Setting any of those Booleans will trigger a rebuild of Collection caches,
|
||||
thus breaking any current iteration over ``Collection.all_objects``.
|
||||
|
||||
|
||||
sys.exit
|
||||
@@ -848,5 +826,5 @@ as if Blender is crashing since ``sys.exit()`` will close Blender immediately.
|
||||
|
||||
For example, the ``argparse`` module will print an error and exit if the arguments are invalid.
|
||||
|
||||
An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of Python code is quitting,
|
||||
An dirty way of troubleshooting this is to set ``sys.exit = None`` and see what line of Python code is quitting,
|
||||
you could of course replace ``sys.exit`` with your own function but manipulating Python in this way is bad practice.
|
||||
|
@@ -1,4 +1,3 @@
|
||||
|
||||
.. _info_overview:
|
||||
|
||||
*******************
|
||||
@@ -6,24 +5,24 @@ Python API Overview
|
||||
*******************
|
||||
|
||||
The purpose of this document is to explain how Python and Blender fit together,
|
||||
covering some of the functionality that may not be obvious from reading the API
|
||||
references and example scripts.
|
||||
covering some of the functionality that may not be obvious from reading the API references
|
||||
and example scripts.
|
||||
|
||||
|
||||
Python in Blender
|
||||
=================
|
||||
|
||||
Blender has an embedded Python interpreter which is loaded when Blender is started and stays
|
||||
active while Blender is running. This interpreter runs scripts to draw the user interface
|
||||
and is used for some of Blender’s internal tools as well.
|
||||
Blender has an embedded Python interpreter which is loaded when Blender is started
|
||||
and stays active while Blender is running. This interpreter runs scripts to draw the user interface
|
||||
and is used for some of Blender's internal tools as well.
|
||||
|
||||
Blender's embedded interpreter provides a typical Python environment, so code from tutorials
|
||||
on how to write Python scripts can also be run with Blender’s interpreter. Blender provides its
|
||||
on how to write Python scripts can also be run with Blender's interpreter. Blender provides its
|
||||
Python modules, such as :mod:`bpy` and :mod:`mathutils`, to the embedded interpreter so they can
|
||||
be imported into a script and give access to Blender's data, classes, and functions. Scripts that
|
||||
deal with Blender data will need to import the modules to work.
|
||||
be imported into a script and give access to Blender's data, classes, and functions.
|
||||
Scripts that deal with Blender data will need to import the modules to work.
|
||||
|
||||
Here is a simple example which moves a vertex attached to an object named **Cube**:
|
||||
Here is a simple example which moves a vertex attached to an object named "Cube":
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -31,7 +30,7 @@ Here is a simple example which moves a vertex attached to an object named **Cube
|
||||
bpy.data.objects["Cube"].data.vertices[0].co.x += 1.0
|
||||
|
||||
This modifies Blender's internal data directly.
|
||||
When you run this in the interactive console you will see the 3D viewport update.
|
||||
When you run this in the interactive console you will see the 3D Viewport update.
|
||||
|
||||
|
||||
The Default Environment
|
||||
@@ -41,7 +40,7 @@ When developing your own scripts it may help to understand how Blender sets up i
|
||||
Many Python scripts come bundled with Blender and can be used as a reference
|
||||
because they use the same API that script authors write tools in.
|
||||
Typical usage for scripts include: user interface, import/export,
|
||||
scene manipulation, automation, defining your own toolset and customization.
|
||||
scene manipulation, automation, defining your own tool set and customization.
|
||||
|
||||
On startup Blender scans the ``scripts/startup/`` directory for Python modules and imports them.
|
||||
The exact location of this directory depends on your installation.
|
||||
@@ -54,8 +53,8 @@ Script Loading
|
||||
This may seem obvious, but it is important to note the difference between
|
||||
executing a script directly and importing a script as a module.
|
||||
|
||||
Extending Blender by executing a script directly means the classes that the script
|
||||
defines remain available inside Blender after the script finishes execution.
|
||||
Extending Blender by executing a script directly means the classes that the script defines
|
||||
remain available inside Blender after the script finishes execution.
|
||||
Using scripts this way makes future access to their classes
|
||||
(to unregister them for example) more difficult compared to importing the scripts as modules.
|
||||
When a script is imported as a module, its class instances will remain
|
||||
@@ -63,12 +62,11 @@ inside the module and can be accessed later on by importing that module again.
|
||||
|
||||
For this reason it is preferable to avoid directly executing scripts that extend Blender by registering classes.
|
||||
|
||||
Here are some ways to run scripts directly in Blender:
|
||||
|
||||
Here are some ways to run scripts directly in Blender.
|
||||
|
||||
- Loaded in the text editor and press **Run Script**.
|
||||
- Loaded in the text editor and press *Run Script*.
|
||||
- Typed or pasted into the interactive console.
|
||||
- Execute a Python file from the command line with Blender, eg:
|
||||
- Execute a Python file from the command line with Blender, e.g:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
@@ -77,24 +75,22 @@ Here are some ways to run scripts directly in Blender.
|
||||
|
||||
To run as modules:
|
||||
|
||||
- The obvious way, ``import some_module`` command from the text window or interactive console.
|
||||
- Open as a text block and tick "Register" option, this will load with the blend file.
|
||||
- copy into one of the directories ``scripts/startup``, where they will be automatically imported on startup.
|
||||
- define as an add-on, enabling the add-on will load it as a Python module.
|
||||
- The obvious way, ``import some_module`` command from the text editor or interactive console.
|
||||
- Open as a text data-block and check the *Register* option, this will load with the blend-file.
|
||||
- Copy into one of the directories ``scripts/startup``, where they will be automatically imported on startup.
|
||||
- Define as an add-on, enabling the add-on will load it as a Python module.
|
||||
|
||||
|
||||
Add-ons
|
||||
-------
|
||||
|
||||
Some of Blenders functionality is best kept optional,
|
||||
alongside scripts loaded at startup we have add-ons which are kept in their own directory ``scripts/addons``,
|
||||
and only load on startup if selected from the user preferences.
|
||||
|
||||
The only difference between add-ons and built-in Python modules is that add-ons must contain a ``bl_info``
|
||||
variable which Blender uses to read metadata such as name, author, category and URL.
|
||||
|
||||
The User Preferences add-on listing uses **bl_info** to display information about each add-on.
|
||||
Some of Blender's functionality is best kept optional,
|
||||
alongside scripts loaded at startup there are add-ons which are kept in their own directory ``scripts/addons``,
|
||||
They are only loaded on startup if selected from the user preferences.
|
||||
|
||||
The only difference between add-ons and built-in Python modules is that add-ons must contain a ``bl_info`` variable
|
||||
which Blender uses to read metadata such as name, author, category and project link.
|
||||
The User Preferences add-on listing uses ``bl_info`` to display information about each add-on.
|
||||
`See Add-ons <https://wiki.blender.org/index.php/Dev:Py/Scripts/Guidelines/Addons>`__
|
||||
for details on the ``bl_info`` dictionary.
|
||||
|
||||
@@ -105,7 +101,7 @@ Integration through Classes
|
||||
Running Python scripts in the text editor is useful for testing but you'll
|
||||
want to extend Blender to make tools accessible like other built-in functionality.
|
||||
|
||||
The Blender Python api allows integration for:
|
||||
The Blender Python API allows integration for:
|
||||
|
||||
- :class:`bpy.types.Panel`
|
||||
- :class:`bpy.types.Menu`
|
||||
@@ -114,13 +110,12 @@ The Blender Python api allows integration for:
|
||||
- :class:`bpy.types.KeyingSet`
|
||||
- :class:`bpy.types.RenderEngine`
|
||||
|
||||
|
||||
This is intentionally limited. Currently, for more advanced features such as mesh modifiers,
|
||||
object types, or shader nodes, C/C++ must be used.
|
||||
|
||||
For Python integration Blender defines methods which are common to all types.
|
||||
This works by creating a Python subclass of a Blender class which contains variables and functions
|
||||
specified by the parent class which are pre-defined to interface with Blender.
|
||||
specified by the parent class which are predefined to interface with Blender.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -137,22 +132,20 @@ For example:
|
||||
|
||||
bpy.utils.register_class(SimpleOperator)
|
||||
|
||||
First note that we subclass a member of :mod:`bpy.types`,
|
||||
First note that it defines a subclass as a member of :mod:`bpy.types`,
|
||||
this is common for all classes which can be integrated with Blender and
|
||||
used so we know if this is an Operator and not a Panel when registering.
|
||||
is used to distinguish an Operator from a Panel when registering.
|
||||
|
||||
Both class properties start with a ``bl_`` prefix.
|
||||
This is a convention used to distinguish Blender properties from those you add yourself.
|
||||
|
||||
Next see the execute function, which takes an instance of the operator and the current context.
|
||||
A common prefix is not used for functions.
|
||||
|
||||
Lastly the register function is called, this takes the class and loads it into Blender. See `Class Registration`_.
|
||||
|
||||
Regarding inheritance, Blender doesn't impose restrictions on the kinds of class inheritance used,
|
||||
the registration checks will use attributes and functions defined in parent classes.
|
||||
|
||||
class mix-in example:
|
||||
Class mix-in example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -173,8 +166,8 @@ While ``__init__()`` and ``__del__()`` will be called if defined,
|
||||
the class instances lifetime only spans the execution.
|
||||
So a panel for example will have a new instance for every redraw,
|
||||
for this reason there is rarely a cause to store variables in the panel instance.
|
||||
Instead, persistent variables should be stored in Blenders
|
||||
ata so that the state can be restored when Blender is restarted.
|
||||
Instead, persistent variables should be stored in Blender's data
|
||||
so that the state can be restored when Blender is restarted.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -182,15 +175,14 @@ ata so that the state can be restored when Blender is restarted.
|
||||
|
||||
So once the class is registered with Blender, instancing the class and calling the functions is left up to Blender.
|
||||
In fact you cannot instance these classes from the script as you would expect with most Python API's.
|
||||
|
||||
To run operators you can call them through the operator api, eg:
|
||||
To run operators you can call them through the operator API, e.g:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import bpy
|
||||
bpy.ops.object.simple_operator()
|
||||
|
||||
User interface classes are given a context in which to draw, buttons window, file header, toolbar etc,
|
||||
User interface classes are given a context in which to draw, buttons, window, file header, toolbar, etc.,
|
||||
then they are drawn when that area is displayed so they are never called by Python scripts directly.
|
||||
|
||||
|
||||
@@ -205,7 +197,7 @@ Module Registration
|
||||
Blender modules loaded at startup require ``register()`` and ``unregister()`` functions.
|
||||
These are the *only* functions that Blender calls from your code, which is otherwise a regular Python module.
|
||||
|
||||
A simple Blender/Python module can look like this:
|
||||
A simple Blender Python module can look like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -225,16 +217,15 @@ A simple Blender/Python module can look like this:
|
||||
|
||||
These functions usually appear at the bottom of the script containing class registration sometimes adding menu items.
|
||||
You can also use them for internal purposes setting up data for your own tools but take care
|
||||
since register won't re-run when a new blend file is loaded.
|
||||
since register won't re-run when a new blend-file is loaded.
|
||||
|
||||
The register/unregister calls are used so it's possible to toggle add-ons and reload scripts while Blender runs.
|
||||
If the register calls were placed in the body of the script, registration would be called on import,
|
||||
meaning there would be no distinction between importing a module or loading its classes into Blender.
|
||||
|
||||
This becomes problematic when a script imports classes from another module
|
||||
making it difficult to manage which classes are being loaded and when.
|
||||
|
||||
The last 2 lines are only for testing:
|
||||
The last two lines are only for testing:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -251,7 +242,6 @@ Class Registration
|
||||
|
||||
Registering a class with Blender results in the class definition being loaded into Blender,
|
||||
where it becomes available alongside existing functionality.
|
||||
|
||||
Once this class is loaded you can access it from :mod:`bpy.types`,
|
||||
using the ``bl_idname`` rather than the classes original name.
|
||||
|
||||
@@ -271,23 +261,23 @@ Using the function arguments ``def execute(self, context, spam)``, will raise an
|
||||
|
||||
``ValueError: expected Operator, SimpleOperator class "execute" function to have 2 args, found 3``
|
||||
|
||||
Using ``bl_idname = 1`` will raise.
|
||||
Using ``bl_idname = 1`` will raise:
|
||||
|
||||
``TypeError: validating class error: Operator.bl_idname expected a string type, not int``
|
||||
|
||||
|
||||
Inter Classes Dependencies
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Inter-Class Dependencies
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When customizing Blender you may want to group your own settings together,
|
||||
after all, they will likely have to co-exist with other scripts.
|
||||
To group these properties classes need to be defined,
|
||||
for groups within groups or collections within groups
|
||||
you can find yourself having to deal with order of registration/unregistration.
|
||||
you can't avoid having to deal with the order of registration/unregistration.
|
||||
|
||||
Custom properties groups are themselves classes which need to be registered.
|
||||
|
||||
Say you want to store material settings for a custom engine.
|
||||
For example, if you want to store material settings for a custom engine:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -311,7 +301,7 @@ Say you want to store material settings for a custom engine.
|
||||
|
||||
.. note::
|
||||
|
||||
*The class must be registered before being used in a property, failing to do so will raise an error:*
|
||||
The class **must be** registered before being used in a property, failing to do so will raise an error:
|
||||
|
||||
``ValueError: bpy_struct "Material" registration error: my_custom_props could not register``
|
||||
|
||||
@@ -341,17 +331,17 @@ Say you want to store material settings for a custom engine.
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
.. note::
|
||||
.. important::
|
||||
|
||||
*The lower most class needs to be registered first and that unregister() is a mirror of register()*
|
||||
The lower most class needs to be registered first and that ``unregister()`` is a mirror of ``register()``.
|
||||
|
||||
|
||||
Manipulating Classes
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Properties can be added and removed as Blender runs,
|
||||
normally happens on register or unregister but for some
|
||||
special cases it may be useful to modify types as the script runs.
|
||||
normally done on register or unregister but for some special cases
|
||||
it may be useful to modify types as the script runs.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -362,7 +352,7 @@ For example:
|
||||
# remove
|
||||
del bpy.types.Object.my_float
|
||||
|
||||
This works just as well for PropertyGroup subclasses you define yourself.
|
||||
This works just as well for ``PropertyGroup`` subclasses you define yourself.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -370,7 +360,7 @@ This works just as well for PropertyGroup subclasses you define yourself.
|
||||
pass
|
||||
MyPropGroup.my_float: bpy.props.FloatProperty()
|
||||
|
||||
...this is equivalent to:
|
||||
This is equivalent to:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -378,11 +368,11 @@ This works just as well for PropertyGroup subclasses you define yourself.
|
||||
my_float: bpy.props.FloatProperty()
|
||||
|
||||
|
||||
Dynamic Defined-Classes (Advanced)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Dynamic Class Definition (Advanced)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In some cases the specifier for data may not be in Blender, renderman shader definitions
|
||||
for example, and it may be useful to define them as types and remove them on the fly.
|
||||
In some cases the specifier for data may not be in Blender, for example a external render engines shader definitions,
|
||||
and it may be useful to define them as types and remove them on the fly.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@@ -1,19 +1,16 @@
|
||||
|
||||
.. _info_quickstart:
|
||||
|
||||
***********************
|
||||
Quickstart Introduction
|
||||
***********************
|
||||
**********
|
||||
Quickstart
|
||||
**********
|
||||
|
||||
Preface
|
||||
=======
|
||||
This :abbr:`API (Application Programming Interface)` is generally stable
|
||||
but some areas are still being extended and improved.
|
||||
|
||||
This API is generally stable but some areas are still being added and improved.
|
||||
|
||||
The Blender/Python API can do the following:
|
||||
.. rubric:: Blender Python API features:
|
||||
|
||||
- Edit any data the user interface can (Scenes, Meshes, Particles etc.).
|
||||
- Modify user preferences, key-maps and themes.
|
||||
- Modify user preferences, keymaps and themes.
|
||||
- Run tools with own settings.
|
||||
- Create user interface elements such as menus, headers and panels.
|
||||
- Create new tools.
|
||||
@@ -21,10 +18,10 @@ The Blender/Python API can do the following:
|
||||
- Create new rendering engines that integrate with Blender.
|
||||
- Subscribe to changes to data and it's properties.
|
||||
- Define new settings in existing Blender data.
|
||||
- Draw in the 3D view using Python.
|
||||
- Draw in the 3D Viewport using Python.
|
||||
|
||||
|
||||
The Blender/Python API **can't** (yet)...
|
||||
.. rubric:: (Still) missing features:
|
||||
|
||||
- Create new space types.
|
||||
- Assign custom properties to every type.
|
||||
@@ -33,22 +30,21 @@ The Blender/Python API **can't** (yet)...
|
||||
Before Starting
|
||||
===============
|
||||
|
||||
This document isn't intended to fully cover each topic.
|
||||
Rather, its purpose is to familiarize you with Blender Python API.
|
||||
|
||||
This document its intended to familiarize you with Blender Python API
|
||||
but not to fully cover each topic.
|
||||
|
||||
A quick list of helpful things to know before starting:
|
||||
|
||||
- Blender uses Python 3.x; some online documentation still assumes 2.x.
|
||||
- Blender uses Python 3.x; some online documentation still assumes version 2.x.
|
||||
- The interactive console is great for testing one-liners.
|
||||
It also has autocompletion so you can inspect the API quickly.
|
||||
- Button tool tips show Python attributes and operator names.
|
||||
- Right clicking on buttons and menu items directly links to API documentation.
|
||||
- For more examples, the text menu has a templates section where some example operators can be found.
|
||||
- Button tooltips show Python attributes and operator names.
|
||||
- The context menu of buttons directly links to this API documentation.
|
||||
- More operator examples can be found in the text editor's template menu.
|
||||
- To examine further scripts distributed with Blender, see:
|
||||
|
||||
| ``scripts/startup/bl_ui`` for the user interface,
|
||||
| ``scripts/startup/bl_operators`` for operators.
|
||||
- ``scripts/startup/bl_ui`` for the user interface.
|
||||
- ``scripts/startup/bl_operators`` for operators.
|
||||
|
||||
Exact location depends on platform, see:
|
||||
:ref:`directory layout docs <blender_manual:blender-directory-layout>`.
|
||||
@@ -59,19 +55,14 @@ Running Scripts
|
||||
|
||||
The two most common ways to execute Python scripts are using the built-in
|
||||
text editor or entering commands in the Python console.
|
||||
|
||||
Both the *Text Editor* and *Python Console* are space types you can select from the view header.
|
||||
|
||||
Both the *Text Editor* and *Python Console* are space types you can select from the header.
|
||||
Rather than manually configuring your spaces for Python development,
|
||||
you may prefer to use the *Scripting* screen, included default with Blender,
|
||||
accessible from the top headers screen selector.
|
||||
you can use the *Scripting* workspace accessible from the Topbar tabs.
|
||||
|
||||
From the text editor you can open ``.py`` files or paste then from the clipboard, then test using *Run Script*.
|
||||
|
||||
The Python Console is typically used for typing in snippets and for testing to get immediate feedback,
|
||||
but can also have entire scripts pasted into it.
|
||||
|
||||
Scripts can also run from the command line with Blender but to learn Blender/Python this isn't essential.
|
||||
Scripts can also run from the command line with Blender but to learn scripting in Blender this isn't essential.
|
||||
|
||||
|
||||
Key Concepts
|
||||
@@ -80,14 +71,13 @@ Key Concepts
|
||||
Data Access
|
||||
-----------
|
||||
|
||||
Accessing DataBlocks
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
Accessing Data-Blocks
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Python accesses Blender's data in the same way as the animation system and user interface;
|
||||
this implies that any setting that can be changed via a button can also be changed from Python.
|
||||
|
||||
Accessing data from the currently loaded blend file is done with the module :mod:`bpy.data`.
|
||||
This gives access to library data. For example:
|
||||
You can access Blender's data with the Python API in the same way as the animation system or user interface;
|
||||
this implies that any setting that can be changed via a button can also be changed with Python.
|
||||
Accessing data from the currently loaded blend-file is done with the module :mod:`bpy.data`.
|
||||
It gives access to library data, for example:
|
||||
|
||||
>>> bpy.data.objects
|
||||
<bpy_collection[3], BlendDataObjects>
|
||||
@@ -99,12 +89,11 @@ This gives access to library data. For example:
|
||||
<bpy_collection[1], BlendDataMaterials>
|
||||
|
||||
|
||||
About Collections
|
||||
^^^^^^^^^^^^^^^^^
|
||||
Accessing Collections
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You'll notice that an index as well as a string can be used to access members of the collection.
|
||||
|
||||
Unlike Python's dictionaries, both methods are acceptable;
|
||||
You will notice that an index as well as a string can be used to access members of the collection.
|
||||
Unlike Python dictionaries, both methods are available;
|
||||
however, the index of a member may change while running Blender.
|
||||
|
||||
>>> list(bpy.data.objects)
|
||||
@@ -120,7 +109,7 @@ however, the index of a member may change while running Blender.
|
||||
Accessing Attributes
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Once you have a data block, such as a material, object, collections etc.,
|
||||
Once you have a data-block, such as a material, object, collection, etc.,
|
||||
its attributes can be accessed much like you would change a setting using the graphical interface.
|
||||
In fact, the tooltip for each button also displays the Python attribute
|
||||
which can help in finding what settings to change in a script.
|
||||
@@ -135,8 +124,8 @@ which can help in finding what settings to change in a script.
|
||||
bpy.data.materials['MyMaterial']
|
||||
|
||||
|
||||
For testing what data to access it's useful to use the "Console", which is its own space type.
|
||||
This supports auto-complete, giving you a fast way to dig into different data in your file.
|
||||
For testing what data to access it's useful to use the Python Console, which is its own space type.
|
||||
This supports auto-complete, giving you a fast way to explore the data in your file.
|
||||
|
||||
Example of a data path that can be quickly found via the console:
|
||||
|
||||
@@ -149,8 +138,8 @@ Example of a data path that can be quickly found via the console:
|
||||
Data Creation/Removal
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Those of you familiar with other Python API's may be surprised that
|
||||
new data-blocks in the bpy API can't be created by calling the class:
|
||||
When you are familiar with other Python APIs you may be surprised that
|
||||
new data-blocks in the bpy API cannot be created by calling the class:
|
||||
|
||||
>>> bpy.types.Mesh()
|
||||
Traceback (most recent call last):
|
||||
@@ -159,10 +148,10 @@ new data-blocks in the bpy API can't be created by calling the class:
|
||||
|
||||
|
||||
This is an intentional part of the API design.
|
||||
The Blender/Python API can't create Blender data that exists outside the main Blender database
|
||||
(accessed through :mod:`bpy.data`), because this data is managed by Blender (save/load/undo/append... etc).
|
||||
The Blender Python API can't create Blender data that exists outside the main Blender database
|
||||
(accessed through :mod:`bpy.data`), because this data is managed by Blender (save, load, undo, append, etc).
|
||||
|
||||
Data is added and removed via methods on the collections in :mod:`bpy.data`, eg:
|
||||
Data is added and removed via methods on the collections in :mod:`bpy.data`, e.g:
|
||||
|
||||
>>> mesh = bpy.data.meshes.new(name="MyMesh")
|
||||
>>> print(mesh)
|
||||
@@ -174,14 +163,12 @@ Data is added and removed via methods on the collections in :mod:`bpy.data`, eg:
|
||||
Custom Properties
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Python can access properties on any datablock that has an ID
|
||||
(data that can be linked in and accessed from :mod:`bpy.data`.
|
||||
When assigning a property, you can make up your own names,
|
||||
these will be created when needed or overwritten if they exist.
|
||||
Python can access properties on any data-block that has an ID
|
||||
(data that can be linked in and accessed from :mod:`bpy.data`).
|
||||
When assigning a property, you can pick your own names,
|
||||
these will be created when needed or overwritten if they already exist.
|
||||
|
||||
This data is saved with the blend file and copied with objects.
|
||||
|
||||
Example:
|
||||
This data is saved with the blend-file and copied with objects, for example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -201,10 +188,10 @@ Example:
|
||||
del collection["MySettings"]
|
||||
|
||||
|
||||
Note that these properties can only be assigned basic Python types.
|
||||
Note that these properties can only be assigned basic Python types:
|
||||
|
||||
- int, float, string
|
||||
- array of ints/floats
|
||||
- array of ints or floats
|
||||
- dictionary (only string keys are supported, values must be basic types too)
|
||||
|
||||
These properties are valid outside of Python. They can be animated by curves or used in driver paths.
|
||||
@@ -218,18 +205,16 @@ it's more common to operate on the user's selection.
|
||||
The context is always available from ``bpy.context`` and can be used to get the active object, scene,
|
||||
tool settings along with many other attributes.
|
||||
|
||||
Common-use cases:
|
||||
Some common use cases are:
|
||||
|
||||
>>> bpy.context.object
|
||||
>>> bpy.context.selected_objects
|
||||
>>> bpy.context.visible_bones
|
||||
|
||||
Note that the context is read-only.
|
||||
These values cannot be modified directly,
|
||||
though they may be changed by running API functions or by using the data API.
|
||||
Note that the context is read-only, which means that these values cannot be modified directly.
|
||||
But they can be changed by running API functions or by using the data API.
|
||||
|
||||
So ``bpy.context.active_object = obj`` will raise an error.
|
||||
|
||||
But ``bpy.context.view_layer.objects.active = obj`` works as expected.
|
||||
|
||||
The context attributes change depending on where they are accessed.
|
||||
@@ -257,7 +242,7 @@ Examples:
|
||||
|
||||
.. tip::
|
||||
|
||||
The :ref:`Operator Cheat Sheet <blender_manual:bpy.ops.wm.operator_cheat_sheet>`.
|
||||
The :ref:`Operator Cheat Sheet <blender_manual:bpy.ops.wm.operator_cheat_sheet>`
|
||||
gives a list of all operators and their default values in Python syntax, along with the generated docs.
|
||||
This is a good way to get an overview of all Blender's operators.
|
||||
|
||||
@@ -265,8 +250,8 @@ Examples:
|
||||
Operator Poll()
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Many operators have a "poll" function which may check that the cursor
|
||||
is in a valid area or that the object is in the correct mode (Edit Mode, Weight Paint etc).
|
||||
Many operators have a "poll" function which checks if the cursor
|
||||
is in a valid area or if the object is in the correct mode (Edit Mode, Weight Paint Mode, etc).
|
||||
When an operator's poll function fails within Python, an exception is raised.
|
||||
|
||||
For example, calling ``bpy.ops.view3d.render_border()`` from the console raises the following error:
|
||||
@@ -275,10 +260,10 @@ For example, calling ``bpy.ops.view3d.render_border()`` from the console raises
|
||||
|
||||
RuntimeError: Operator bpy.ops.view3d.render_border.poll() failed, context is incorrect
|
||||
|
||||
In this case the context must be the 3d view with an active camera.
|
||||
In this case the context must be the 3D Viewport with an active camera.
|
||||
|
||||
To avoid using try/except clauses wherever operators are called you can call the operators
|
||||
own ``poll()`` function to check if it can run in the current context.
|
||||
To avoid using try-except clauses wherever operators are called, you can call the operators
|
||||
own ``poll()`` function to check if it can run the operator in the current context.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -291,11 +276,10 @@ Integration
|
||||
|
||||
Python scripts can integrate with Blender in the following ways:
|
||||
|
||||
- By defining a rendering engine.
|
||||
- By defining a render engine.
|
||||
- By defining operators.
|
||||
- By defining menus, headers and panels.
|
||||
- By inserting new buttons into existing menus, headers and panels
|
||||
|
||||
- By inserting new buttons into existing menus, headers and panels.
|
||||
|
||||
In Python, this is done by defining a class, which is a subclass of an existing type.
|
||||
|
||||
@@ -306,56 +290,52 @@ Example Operator
|
||||
.. literalinclude:: __/__/__/release/scripts/templates_py/operator_simple.py
|
||||
|
||||
Once this script runs, ``SimpleOperator`` is registered with Blender
|
||||
and can be called from the operator search popup or added to the toolbar.
|
||||
and can be called from Operator Search or added to the toolbar.
|
||||
|
||||
To run the script:
|
||||
|
||||
#. Highlight the above code then press :kbd:`Ctrl-C` to copy it.
|
||||
#. Start Blender
|
||||
#. Press :kbd:`Ctrl-Right` twice to change to the Scripting layout.
|
||||
#. Click the button labeled ``New`` and the confirmation pop up in order to create a new text block.
|
||||
#. Press :kbd:`Ctrl-V` to paste the code into the text panel (the upper left frame).
|
||||
#. Click on the button **Run Script**.
|
||||
#. Start Blender and switch to the Scripting workspace.
|
||||
#. Click the *New* button in the text editor to create a new text data-block.
|
||||
#. Copy the code from above and paste it into the text editor.
|
||||
#. Click on the *Run Script* button.
|
||||
#. Move your cursor into the 3D Viewport,
|
||||
open the :ref:`operator search menu <blender_manual:bpy.ops.wm.search_menu>`,
|
||||
open the :ref:`Operator Search menu <blender_manual:bpy.ops.wm.search_menu>`,
|
||||
and type "Simple".
|
||||
#. Click on the "Simple Operator" item found in search.
|
||||
|
||||
.. seealso::
|
||||
|
||||
.. seealso:: The class members with the ``bl_`` prefix are documented in the API
|
||||
reference :class:`bpy.types.Operator`
|
||||
The class members with the ``bl_`` prefix are documented in the API reference :class:`bpy.types.Operator`.
|
||||
|
||||
.. note::
|
||||
|
||||
The output from the ``main`` function is sent to the terminal;
|
||||
in order to see this, be sure to :ref:`use the terminal <use_the_terminal>`.
|
||||
|
||||
|
||||
Example Panel
|
||||
-------------
|
||||
|
||||
Panels register themselves as a class, like an operator.
|
||||
Panels are registered as a class, like an operator.
|
||||
Notice the extra ``bl_`` variables used to set the context they display in.
|
||||
|
||||
.. literalinclude:: __/__/__/release/scripts/templates_py/ui_panel_simple.py
|
||||
|
||||
To run the script:
|
||||
|
||||
#. Highlight the above code then press :kbd:`Ctrl-C` to copy it.
|
||||
#. Start Blender.
|
||||
#. Click on the tab for the *Scripting* workspace.
|
||||
#. Click the button labeled ``New`` to create a new text block.
|
||||
#. Press :kbd:`Ctrl-V` to paste the code into the text panel (the upper left frame).
|
||||
#. Click on the button **Run Script**.
|
||||
|
||||
#. Start Blender and switch to the Scripting workspace.
|
||||
#. Click the *New* button in the text editor to create a new text data-block.
|
||||
#. Copy the code from above and paste it into the text editor.
|
||||
#. Click on the *Run Script* button.
|
||||
|
||||
To view the results:
|
||||
|
||||
#. Select the the default cube.
|
||||
#. Select the default cube.
|
||||
#. Click on the Object properties icon in the buttons panel (far right; appears as a tiny cube).
|
||||
#. Scroll down to see a panel named **Hello World Panel**.
|
||||
#. Changing the object name also updates **Hello World Panel's** Name: field.
|
||||
#. Scroll down to see a panel named "Hello World Panel".
|
||||
#. Changing the object name also updates *Hello World Panel's* name: field.
|
||||
|
||||
Note the row distribution and the label and properties that are available through the code.
|
||||
Note the row distribution and the label and properties that are defined through the code.
|
||||
|
||||
.. seealso:: :class:`bpy.types.Panel`
|
||||
|
||||
@@ -364,8 +344,7 @@ Types
|
||||
=====
|
||||
|
||||
Blender defines a number of Python types but also uses Python native types.
|
||||
|
||||
Blender's Python API can be split up into 3 categories.
|
||||
Blender's Python API can be split up into three categories.
|
||||
|
||||
|
||||
Native Types
|
||||
@@ -374,7 +353,7 @@ Native Types
|
||||
In simple cases returning a number or a string as a custom type would be cumbersome,
|
||||
so these are accessed as normal Python types.
|
||||
|
||||
- Blender float/int/boolean -> float/int/boolean
|
||||
- Blender float, int, boolean -> float, int, boolean
|
||||
- Blender enumerator -> string
|
||||
|
||||
>>> C.object.rotation_mode = 'AXIS_ANGLE'
|
||||
@@ -393,11 +372,10 @@ so these are accessed as normal Python types.
|
||||
Internal Types
|
||||
--------------
|
||||
|
||||
Used for Blender data-blocks and collections: :class:`bpy.types.bpy_struct`
|
||||
:class:`bpy.types.bpy_struct` is used for Blender data-blocks and collections.
|
||||
Also for data that contains its own attributes: collections, meshes, bones, scenes, etc.
|
||||
|
||||
For data that contains its own attributes collections/meshes/bones/scenes... etc.
|
||||
|
||||
There are 2 main types that wrap Blenders data, one for data-blocks
|
||||
There are two main types that wrap Blender's data, one for data-blocks
|
||||
(known internally as ``bpy_struct``), another for properties.
|
||||
|
||||
>>> bpy.context.object
|
||||
@@ -406,14 +384,13 @@ There are 2 main types that wrap Blenders data, one for data-blocks
|
||||
>>> C.scene.objects
|
||||
bpy.data.scenes['Scene'].objects
|
||||
|
||||
Note that these types reference Blender's data so modifying them is immediately visible.
|
||||
Note that these types reference Blender's data so modifying them is visible immediately.
|
||||
|
||||
|
||||
Mathutils Types
|
||||
---------------
|
||||
|
||||
Used for vectors, quaternion, eulers, matrix and color types, accessible from :mod:`mathutils`
|
||||
|
||||
Accessible from :mod:`mathutils` are vectors, quaternions, Euler angles, matrix and color types.
|
||||
Some attributes such as :class:`bpy.types.Object.location`,
|
||||
:class:`bpy.types.PoseBone.rotation_euler` and :class:`bpy.types.Scene.cursor_location`
|
||||
can be accessed as special math types which can be used together and manipulated in various useful ways.
|
||||
@@ -422,14 +399,13 @@ Example of a matrix, vector multiplication:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bpy.context.object.matrix_world * bpy.context.object.data.verts[0].co
|
||||
bpy.context.object.matrix_world @ bpy.context.object.data.verts[0].co
|
||||
|
||||
.. note::
|
||||
|
||||
mathutils types keep a reference to Blender's internal data so changes can
|
||||
be applied back.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
@@ -449,13 +425,11 @@ Example of a matrix, vector multiplication:
|
||||
Animation
|
||||
=========
|
||||
|
||||
There are 2 ways to add keyframes through Python.
|
||||
There are two ways to add keyframes through Python.
|
||||
|
||||
The first is through key properties directly, which is similar to inserting a keyframe from the button as a user.
|
||||
The first is through key properties directly, which is like inserting a keyframe from the button as a user.
|
||||
You can also manually create the curves and keyframe data, then set the path to the property.
|
||||
Here are examples of both methods.
|
||||
|
||||
Both examples insert a keyframe on the active object's Z axis.
|
||||
Here are examples of both methods. Both insert a keyframe on the active object's Z axis.
|
||||
|
||||
Simple example:
|
||||
|
||||
@@ -467,7 +441,7 @@ Simple example:
|
||||
obj.location[2] = 1.0
|
||||
obj.keyframe_insert(data_path="location", frame=20.0, index=2)
|
||||
|
||||
Using Low-Level Functions:
|
||||
Using low-level functions:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@@ -4,23 +4,22 @@ Tips and Tricks
|
||||
***************
|
||||
|
||||
Here are various suggestions that you might find useful when writing scripts.
|
||||
|
||||
Some of these are just Python features that scripters may not have thought to use with Blender,
|
||||
others are Blender specific.
|
||||
Some of these are just Python features that you may not have thought to use with Blender,
|
||||
others are Blender-specific.
|
||||
|
||||
|
||||
.. _use_the_terminal:
|
||||
|
||||
Use The Terminal
|
||||
Use the Terminal
|
||||
================
|
||||
|
||||
When writing Python scripts, it's useful to have a terminal open,
|
||||
this is not the built-in Python console but a terminal application which is used to start Blender.
|
||||
|
||||
There are 3 main uses for the terminal, these are:
|
||||
The three main use cases for the terminal are:
|
||||
|
||||
- You can see the output of ``print()`` as your script runs, which is useful to view debug info.
|
||||
- The error trace-back is printed in full to the terminal which won't always generate an error popup in
|
||||
- The error traceback is printed in full to the terminal which won't always generate an report message in
|
||||
Blender's user interface (depending on how the script is executed).
|
||||
- If the script runs for too long or you accidentally enter an infinite loop,
|
||||
:kbd:`Ctrl-C` in the terminal (:kbd:`Ctrl-Break` on Windows) will quit the script early.
|
||||
@@ -28,26 +27,25 @@ There are 3 main uses for the terminal, these are:
|
||||
.. note::
|
||||
|
||||
For Linux and macOS users this means starting the terminal first, then running Blender from within it.
|
||||
On Windows the terminal can be enabled from the help menu.
|
||||
On Windows the terminal can be enabled from the Help menu.
|
||||
|
||||
|
||||
Interface Tricks
|
||||
================
|
||||
|
||||
|
||||
Access Operator Commands
|
||||
------------------------
|
||||
|
||||
You may have noticed that the tooltip for menu items and buttons includes the ``bpy.ops.[...])`` command
|
||||
You may have noticed that the tooltip for menu items and buttons includes the ``bpy.ops.[...]`` command
|
||||
to run that button, a handy (hidden) feature is that you can press :kbd:`Ctrl-C` over
|
||||
any menu item/button to copy this command into the clipboard.
|
||||
any menu item or button to copy this command into the clipboard.
|
||||
|
||||
|
||||
Access Data Path
|
||||
----------------
|
||||
|
||||
To find the path from an :class:`ID` datablock to its setting isn't always so simple since it may be nested away.
|
||||
To get this quickly you can right click on the setting and select select **Copy Data Path**,
|
||||
To find the path from an :class:`ID` data-block to its setting isn't always so simple since it may be nested away.
|
||||
To get this quickly open the context menu of the setting and select *Copy Data Path*,
|
||||
if this can't be generated, only the property name is copied.
|
||||
|
||||
.. note::
|
||||
@@ -62,11 +60,10 @@ if this can't be generated, only the property name is copied.
|
||||
Show All Operators
|
||||
==================
|
||||
|
||||
While Blender logs operators in the Info space,
|
||||
this only reports operators with the ``REGISTER`` option enabeld so as not to flood the *Info* view
|
||||
While Blender logs operators in the Info editor,
|
||||
this only reports operators with the ``REGISTER`` option enabled so as not to flood the *Info* view
|
||||
with calls to ``bpy.ops.view3d.smoothview`` and ``bpy.ops.view3d.zoom``.
|
||||
|
||||
However, for testing it can be useful to see **every** operator called in a terminal,
|
||||
Yet for testing it can be useful to see **every** operator called in a terminal,
|
||||
do this by enabling the debug option either by passing the ``--debug-wm`` argument when starting Blender
|
||||
or by setting :mod:`bpy.app.debug_wm` to ``True`` while Blender is running.
|
||||
|
||||
@@ -74,20 +71,18 @@ or by setting :mod:`bpy.app.debug_wm` to ``True`` while Blender is running.
|
||||
Use an External Editor
|
||||
======================
|
||||
|
||||
Blenders text editor is fine for small changes and writing tests but its not full featured,
|
||||
Blender's text editor is fine for small changes and writing tests but its not full featured,
|
||||
for larger projects you'll probably want to use a standalone editor or Python IDE.
|
||||
|
||||
Editing a text file externally and having the same text open in Blender does work but isn't that optimal
|
||||
so here are 2 ways you can easily use an external file from Blender.
|
||||
|
||||
Using the following examples you'll still need textblock in Blender to execute,
|
||||
Editing a text file externally and having the same text open in Blender does work
|
||||
but isn't that optimal so here are two ways you can use an external file from Blender.
|
||||
Using the following examples you'll still need text data-block in Blender to execute,
|
||||
but reference an external file rather than including it directly.
|
||||
|
||||
|
||||
Executing External Scripts
|
||||
--------------------------
|
||||
|
||||
This is the equivalent to running the script directly, referencing a scripts path from a 2 line text-block.
|
||||
This is the equivalent to running the script directly, referencing a scripts path from a two line code block.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -95,7 +90,7 @@ This is the equivalent to running the script directly, referencing a scripts pat
|
||||
exec(compile(open(filename).read(), filename, 'exec'))
|
||||
|
||||
|
||||
You might want to reference a script relative to the blend file.
|
||||
You might want to reference a script relative to the blend-file.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -128,9 +123,10 @@ has to call a function in the module, in this case ``main()`` but it can be any
|
||||
an advantage with this is you can pass arguments to the function from this
|
||||
small script which is often useful for testing different settings quickly.
|
||||
|
||||
The other issue with this is the script has to be in Pythons module search path.
|
||||
While this is not best practice - for testing you can extend the search path,
|
||||
this example adds the current blend files directory to the search path, then loads the script as a module.
|
||||
The other issue with this is the script has to be in Python's module search path.
|
||||
While this is not best practice -- for testing purposes you can extend the search path,
|
||||
this following example adds the current blend-files directory to the search path
|
||||
and then loads the script as a module.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -148,42 +144,40 @@ this example adds the current blend files directory to the search path, then loa
|
||||
myscript.main()
|
||||
|
||||
|
||||
Don't Use Blender!
|
||||
==================
|
||||
|
||||
While developing your own scripts Blenders interface can get in the way,
|
||||
manually reloading, running the scripts, opening file import etc. adds overhead.
|
||||
Use Blender without it's User Interface
|
||||
=======================================
|
||||
|
||||
While developing your own scripts Blender's interface can get in the way,
|
||||
manually reloading, running the scripts, opening file import, etc. adds overhead.
|
||||
For scripts that are not interactive it can end up being more efficient not to use
|
||||
Blenders interface at all and instead execute the script on the command line.
|
||||
Blender's interface at all and instead execute the script on the command line.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
blender --background --python myscript.py
|
||||
|
||||
|
||||
You might want to run this with a blend file so the script has some data to operate on.
|
||||
You might want to run this with a blend-file so the script has some data to operate on.
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
blender myscene.blend --background --python myscript.py
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Depending on your setup you might have to enter the full path to the Blender executable.
|
||||
|
||||
|
||||
Once the script is running properly in background mode, you'll want to check the output of the script,
|
||||
this depends completely on the task at hand however here are some suggestions.
|
||||
this depends completely on the task at hand, however, here are some suggestions:
|
||||
|
||||
- render the output to an image, use an image viewer and keep writing over the same image each time.
|
||||
- save a new blend file, or export the file using one of Blenders exporters.
|
||||
- if the results can be displayed as text - print them or write them to a file.
|
||||
- Render the output to an image, use an image viewer and keep writing over the same image each time.
|
||||
- Save a new blend-file, or export the file using one of Blender's exporters.
|
||||
- If the results can be displayed as text then print them or write them to a file.
|
||||
|
||||
|
||||
While this can take a little time to setup, it can be well worth the effort
|
||||
to reduce the time it takes to test changes - you can even have
|
||||
to reduce the time it takes to test changes. You can even have
|
||||
Blender running the script every few seconds with a viewer updating the results,
|
||||
so no need to leave your text editor to see changes.
|
||||
|
||||
@@ -200,7 +194,7 @@ but to quickly setup your own custom pipeline or writing one-off scripts this ca
|
||||
|
||||
Examples include:
|
||||
|
||||
- Run The Gimp in batch mode to execute custom scripts for advanced image processing.
|
||||
- Run Gimp in batch mode to execute custom scripts for advanced image processing.
|
||||
- Write out 3D models to use external mesh manipulation tools and read back in the results.
|
||||
- Convert files into recognizable formats before reading.
|
||||
|
||||
@@ -209,15 +203,16 @@ Bundled Python & Extensions
|
||||
===========================
|
||||
|
||||
The Blender releases distributed from blender.org include a complete Python installation on all platforms,
|
||||
this has the disadvantage that any extensions you have installed in your systems Python won't be found by Blender.
|
||||
this has the disadvantage that any extensions you have installed on your system's Python environment
|
||||
will not be found by Blender.
|
||||
|
||||
There are 2 ways around this:
|
||||
There are two ways to work around this:
|
||||
|
||||
- Remove Blender Python sub-directory, Blender will then fallback on the systems Python and use that instead.
|
||||
- Remove Blender Python subdirectory, Blender will then fallback on the system's Python and use that instead.
|
||||
|
||||
Depending on your platform,
|
||||
you may need to explicitly reference the location of your Python installation using the
|
||||
``PYTHONPATH`` environment variable, eg:
|
||||
you may need to explicitly reference the location of your Python installation using
|
||||
the ``PYTHONPATH`` environment variable, e.g:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
@@ -226,21 +221,21 @@ There are 2 ways around this:
|
||||
.. warning::
|
||||
|
||||
The Python (major, minor) version must match the one that Blender comes with.
|
||||
Therefor can't use Python 3.6 with Blender built to use Python 3.7.
|
||||
Therefor you can't use Python 3.6 with Blender built to use Python 3.7.
|
||||
|
||||
- Copy or link the extensions into Blender's Python sub-directory so Blender can access them,
|
||||
you could also copy the entire Python installation into Blenders sub-directory,
|
||||
- Copy or link the extensions into Blender's Python subdirectory so Blender can access them,
|
||||
you can also copy the entire Python installation into Blender's subdirectory,
|
||||
replacing the one Blender comes with.
|
||||
This works as long as the Python versions match and the paths are created in the same relative locations.
|
||||
Doing this has the advantage that you can redistribute this bundle to others with Blender
|
||||
including any extensions you rely on.
|
||||
|
||||
|
||||
Drop Into a Python Interpreter in Your Script
|
||||
=============================================
|
||||
Insert a Python Interpreter into your Script
|
||||
============================================
|
||||
|
||||
In the middle of a script you may want to inspect some variables,
|
||||
run some function and generally dig about to see what's going on.
|
||||
In the middle of a script you may want to inspect variables,
|
||||
run functions and inspect the flow.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -248,7 +243,7 @@ run some function and generally dig about to see what's going on.
|
||||
code.interact(local=locals())
|
||||
|
||||
|
||||
If you want to access both global and local variables do this...
|
||||
If you want to access both global and local variables run this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -266,7 +261,7 @@ The next example is an equivalent single line version of the script above which
|
||||
|
||||
|
||||
``code.interact`` can be added at any line in the script
|
||||
and will pause the script an launch an interactive interpreter in the terminal,
|
||||
and will pause the script to launch an interactive interpreter in the terminal,
|
||||
when you're done you can quit the interpreter and the script will continue execution.
|
||||
|
||||
|
||||
@@ -279,13 +274,14 @@ The IPython prompt has auto-complete and some useful features that the standard
|
||||
IPython.embed()
|
||||
|
||||
|
||||
Admittedly this highlights the lack of any Python debugging support built into Blender, but its still handy to know.
|
||||
Admittedly this highlights the lack of any Python debugging support built into Blender,
|
||||
but its still a handy thing to know.
|
||||
|
||||
|
||||
Advanced
|
||||
========
|
||||
|
||||
|
||||
Blender as a module
|
||||
Blender as a Module
|
||||
-------------------
|
||||
|
||||
From a Python perspective it's nicer to have everything as an extension
|
||||
@@ -293,26 +289,22 @@ which lets the Python script combine many components.
|
||||
|
||||
Advantages include:
|
||||
|
||||
- you can use external editors/IDE's with Blenders Python API and execute scripts within the IDE
|
||||
- You can use external editors or IDEs with Blender's Python API and execute scripts within the IDE
|
||||
(step over code, inspect variables as the script runs).
|
||||
- editors/IDE's can auto complete Blender modules & variables.
|
||||
- existing scripts can import Blender API's without having to run inside Blender.
|
||||
|
||||
- Editors or IDEs can auto-complete Blender modules and variables.
|
||||
- Existing scripts can import Blender APIs without having to be run inside of Blender.
|
||||
|
||||
This is marked advanced because to run Blender as a Python module requires a special build option.
|
||||
|
||||
For instructions on building see
|
||||
`Building Blender as a Python module <https://wiki.blender.org/wiki/Building_Blender/Other/BlenderAsPyModule>`_
|
||||
`Building Blender as a Python module <https://wiki.blender.org/wiki/Building_Blender/Other/BlenderAsPyModule>`__.
|
||||
|
||||
|
||||
Python Safety (Build Option)
|
||||
----------------------------
|
||||
|
||||
Since it's possible to access data which has been removed (see Gotcha's),
|
||||
this can be hard to track down the cause of crashes.
|
||||
|
||||
Since it's possible to access data which has been removed (see :doc:`Gotchas <info_gotcha>`),
|
||||
can make it hard to track down the cause of crashes.
|
||||
To raise Python exceptions on accessing freed data (rather than crashing),
|
||||
enable the CMake build option ``WITH_PYTHON_SAFETY``.
|
||||
|
||||
This enables data tracking which makes data access about 2x slower
|
||||
This enables data tracking which makes data access about two times slower
|
||||
which is why the option isn't enabled in release builds.
|
||||
|
@@ -83,6 +83,8 @@ import inspect
|
||||
import shutil
|
||||
import logging
|
||||
|
||||
from textwrap import indent
|
||||
|
||||
from platform import platform
|
||||
PLATFORM = platform().split('-')[0].lower() # 'linux', 'darwin', 'windows'
|
||||
|
||||
@@ -357,7 +359,7 @@ INFO_DOCS = (
|
||||
("info_tips_and_tricks.rst",
|
||||
"Tips and Tricks: Hints to help you while writing scripts for Blender"),
|
||||
("info_gotcha.rst",
|
||||
"Gotcha's: some of the problems you may come up against when writing scripts"),
|
||||
"Gotcha's: some of the problems you may encounter when writing scripts"),
|
||||
("change_log.rst", "List of changes since last Blender release"),
|
||||
)
|
||||
|
||||
@@ -438,25 +440,30 @@ if ARGS.sphinx_build:
|
||||
|
||||
if ARGS.log:
|
||||
SPHINX_BUILD_LOG = os.path.join(ARGS.output_dir, ".sphinx-build.log")
|
||||
SPHINX_BUILD = ["sphinx-build",
|
||||
"-w", SPHINX_BUILD_LOG,
|
||||
SPHINX_IN, SPHINX_OUT]
|
||||
SPHINX_BUILD = [
|
||||
"sphinx-build",
|
||||
"-w", SPHINX_BUILD_LOG,
|
||||
SPHINX_IN, SPHINX_OUT,
|
||||
]
|
||||
|
||||
# pdf build
|
||||
if ARGS.sphinx_build_pdf:
|
||||
SPHINX_OUT_PDF = os.path.join(ARGS.output_dir, "sphinx-out_pdf")
|
||||
SPHINX_BUILD_PDF = ["sphinx-build",
|
||||
"-b", "latex",
|
||||
SPHINX_IN, SPHINX_OUT_PDF]
|
||||
SPHINX_BUILD_PDF = [
|
||||
"sphinx-build",
|
||||
"-b", "latex",
|
||||
SPHINX_IN, SPHINX_OUT_PDF,
|
||||
]
|
||||
SPHINX_MAKE_PDF = ["make", "-C", SPHINX_OUT_PDF]
|
||||
SPHINX_MAKE_PDF_STDOUT = None
|
||||
|
||||
if ARGS.log:
|
||||
SPHINX_BUILD_PDF_LOG = os.path.join(ARGS.output_dir, ".sphinx-build_pdf.log")
|
||||
SPHINX_BUILD_PDF = ["sphinx-build", "-b", "latex",
|
||||
"-w", SPHINX_BUILD_PDF_LOG,
|
||||
SPHINX_IN, SPHINX_OUT_PDF]
|
||||
|
||||
SPHINX_BUILD_PDF = [
|
||||
"sphinx-build", "-b", "latex",
|
||||
"-w", SPHINX_BUILD_PDF_LOG,
|
||||
SPHINX_IN, SPHINX_OUT_PDF,
|
||||
]
|
||||
sphinx_make_pdf_log = os.path.join(ARGS.output_dir, ".latex_make.log")
|
||||
SPHINX_MAKE_PDF_STDOUT = open(sphinx_make_pdf_log, "w", encoding="utf-8")
|
||||
|
||||
@@ -1026,6 +1033,7 @@ context_type_map = {
|
||||
"gpencil": ("GreasePencil", False),
|
||||
"gpencil_data": ("GreasePencil", False),
|
||||
"gpencil_data_owner": ("ID", False),
|
||||
"hair": ("Hair", False),
|
||||
"image_paint_object": ("Object", False),
|
||||
"lattice": ("Lattice", False),
|
||||
"light": ("Light", False),
|
||||
@@ -1042,6 +1050,7 @@ context_type_map = {
|
||||
"particle_settings": ("ParticleSettings", False),
|
||||
"particle_system": ("ParticleSystem", False),
|
||||
"particle_system_editable": ("ParticleSystem", False),
|
||||
"pointcloud": ("PointCloud", False),
|
||||
"pose_bone": ("PoseBone", False),
|
||||
"pose_object": ("Object", False),
|
||||
"scene": ("Scene", False),
|
||||
@@ -1196,12 +1205,15 @@ def pyrna_enum2sphinx(prop, use_empty_descriptions=False):
|
||||
break
|
||||
|
||||
if ok:
|
||||
return "".join(["* ``%s`` %s.\n" %
|
||||
(identifier,
|
||||
", ".join(escape_rst(val) for val in (name, description) if val),
|
||||
)
|
||||
for identifier, name, description in prop.enum_items
|
||||
])
|
||||
return "".join([
|
||||
"* ``%s``\n"
|
||||
"%s.\n" % (
|
||||
identifier,
|
||||
# Account for multi-line enum descriptions, allowing this to be a block of text.
|
||||
indent(", ".join(escape_rst(val) for val in (name, description) if val) or "Undocumented", " "),
|
||||
)
|
||||
for identifier, name, description in prop.enum_items
|
||||
])
|
||||
else:
|
||||
return ""
|
||||
|
||||
@@ -1268,7 +1280,7 @@ def pyrna2sphinx(basepath):
|
||||
fw(ident + ":%s%s:\n\n" % (id_name, identifier))
|
||||
|
||||
if prop.name or prop.description:
|
||||
fw(ident + " " + ", ".join(val for val in (prop.name, prop.description) if val) + "\n\n")
|
||||
fw(indent(", ".join(val for val in (prop.name, prop.description) if val), ident + " ") + "\n\n")
|
||||
|
||||
# special exception, can't use generic code here for enums
|
||||
if enum_text:
|
||||
@@ -1714,7 +1726,7 @@ class PatchedPythonDomain(PythonDomain):
|
||||
# end workaround
|
||||
|
||||
fw("def setup(app):\n")
|
||||
fw(" app.add_stylesheet('css/theme_overrides.css')\n")
|
||||
fw(" app.add_css_file('css/theme_overrides.css')\n")
|
||||
fw(" app.add_domain(PatchedPythonDomain, override=True)\n\n")
|
||||
|
||||
file.close()
|
||||
|
@@ -118,20 +118,19 @@ def main():
|
||||
|
||||
# III) Get Blender version info.
|
||||
getver_file = os.path.join(tmp_dir, "blendver.txt")
|
||||
getver_script = (
|
||||
"import sys, bpy\n"
|
||||
"with open(sys.argv[-1], 'w') as f:\n"
|
||||
" is_release = bpy.app.version_cycle in {'rc', 'release'}\n"
|
||||
" is_beta = bpy.app.version_cycle in {'beta'}\n"
|
||||
" branch = bpy.app.build_branch.split()[0].decode()\n"
|
||||
" f.write('%d\\n' % is_release)\n"
|
||||
" f.write('%d\\n' % is_beta)\n"
|
||||
" f.write('%s\\n' % branch)\n"
|
||||
" f.write('%d.%d\\n' % (bpy.app.version[0], bpy.app.version[1]))\n"
|
||||
" f.write('%d.%d\\n' % (bpy.app.version[0], bpy.app.version[1])\n"
|
||||
" if (is_release or is_beta) else '%s\\n' % branch)\n"
|
||||
" f.write('%d_%d' % (bpy.app.version[0], bpy.app.version[1]))\n"
|
||||
)
|
||||
getver_script = (r"""import sys, bpy
|
||||
with open(sys.argv[-1], 'w') as f:
|
||||
is_release = bpy.app.version_cycle in {'rc', 'release'}
|
||||
is_beta = bpy.app.version_cycle in {'beta'}
|
||||
branch = bpy.app.build_branch.split()[0].decode()
|
||||
f.write('%d\n' % is_release)
|
||||
f.write('%d\n' % is_beta)
|
||||
f.write('%s\n' % branch)
|
||||
f.write('%d.%d\n' % (bpy.app.version[0], bpy.app.version[1]))
|
||||
f.write('%d.%d\n' % (bpy.app.version[0], bpy.app.version[1])
|
||||
if (is_release or is_beta) else '%s\n' % branch)
|
||||
f.write('%d_%d' % (bpy.app.version[0], bpy.app.version[1]))
|
||||
""")
|
||||
get_ver_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
|
||||
"--python-expr", getver_script, "--", getver_file)
|
||||
subprocess.run(get_ver_cmd)
|
||||
|
42
extern/audaspace/plugins/sdl/SDLDevice.cpp
vendored
42
extern/audaspace/plugins/sdl/SDLDevice.cpp
vendored
@@ -52,7 +52,7 @@ SDLDevice::SDLDevice(DeviceSpecs specs, int buffersize) :
|
||||
if(specs.channels == CHANNELS_INVALID)
|
||||
specs.channels = CHANNELS_STEREO;
|
||||
if(specs.format == FORMAT_INVALID)
|
||||
specs.format = FORMAT_S16;
|
||||
specs.format = FORMAT_FLOAT32;
|
||||
if(specs.rate == RATE_INVALID)
|
||||
specs.rate = RATE_48000;
|
||||
|
||||
@@ -61,10 +61,25 @@ SDLDevice::SDLDevice(DeviceSpecs specs, int buffersize) :
|
||||
SDL_AudioSpec format, obtained;
|
||||
|
||||
format.freq = m_specs.rate;
|
||||
if(m_specs.format == FORMAT_U8)
|
||||
switch(m_specs.format)
|
||||
{
|
||||
case FORMAT_U8:
|
||||
format.format = AUDIO_U8;
|
||||
else
|
||||
break;
|
||||
case FORMAT_S16:
|
||||
format.format = AUDIO_S16SYS;
|
||||
break;
|
||||
case FORMAT_S32:
|
||||
format.format = AUDIO_S32SYS;
|
||||
break;
|
||||
case FORMAT_FLOAT32:
|
||||
format.format = AUDIO_F32SYS;
|
||||
break;
|
||||
default:
|
||||
format.format = AUDIO_F32SYS;
|
||||
break;
|
||||
}
|
||||
|
||||
format.channels = m_specs.channels;
|
||||
format.samples = buffersize;
|
||||
format.callback = SDLDevice::SDL_mix;
|
||||
@@ -75,14 +90,25 @@ SDLDevice::SDLDevice(DeviceSpecs specs, int buffersize) :
|
||||
|
||||
m_specs.rate = (SampleRate)obtained.freq;
|
||||
m_specs.channels = (Channels)obtained.channels;
|
||||
if(obtained.format == AUDIO_U8)
|
||||
m_specs.format = FORMAT_U8;
|
||||
else if(obtained.format == AUDIO_S16LSB || obtained.format == AUDIO_S16MSB)
|
||||
m_specs.format = FORMAT_S16;
|
||||
else
|
||||
|
||||
switch(obtained.format)
|
||||
{
|
||||
case AUDIO_U8:
|
||||
m_specs.format = FORMAT_U8;
|
||||
break;
|
||||
case AUDIO_S16SYS:
|
||||
m_specs.format = FORMAT_S16;
|
||||
break;
|
||||
case AUDIO_S32SYS:
|
||||
m_specs.format = FORMAT_S32;
|
||||
break;
|
||||
case AUDIO_F32SYS:
|
||||
m_specs.format = FORMAT_FLOAT32;
|
||||
break;
|
||||
default:
|
||||
SDL_CloseAudio();
|
||||
AUD_THROW(DeviceException, "The sample format obtained from SDL is not supported.");
|
||||
break;
|
||||
}
|
||||
|
||||
create();
|
||||
|
576
extern/ceres/CMakeLists.txt
vendored
576
extern/ceres/CMakeLists.txt
vendored
@@ -37,223 +37,279 @@ set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
internal/ceres/array_utils.cc
|
||||
internal/ceres/blas.cc
|
||||
internal/ceres/block_evaluate_preparer.cc
|
||||
internal/ceres/block_jacobian_writer.cc
|
||||
internal/ceres/block_jacobi_preconditioner.cc
|
||||
internal/ceres/block_random_access_dense_matrix.cc
|
||||
internal/ceres/block_random_access_diagonal_matrix.cc
|
||||
internal/ceres/block_random_access_matrix.cc
|
||||
internal/ceres/block_random_access_sparse_matrix.cc
|
||||
internal/ceres/block_sparse_matrix.cc
|
||||
internal/ceres/block_structure.cc
|
||||
internal/ceres/callbacks.cc
|
||||
internal/ceres/c_api.cc
|
||||
internal/ceres/cgnr_solver.cc
|
||||
internal/ceres/compressed_col_sparse_matrix_utils.cc
|
||||
internal/ceres/compressed_row_jacobian_writer.cc
|
||||
internal/ceres/compressed_row_sparse_matrix.cc
|
||||
internal/ceres/conditioned_cost_function.cc
|
||||
internal/ceres/conjugate_gradients_solver.cc
|
||||
internal/ceres/coordinate_descent_minimizer.cc
|
||||
internal/ceres/corrector.cc
|
||||
internal/ceres/covariance.cc
|
||||
internal/ceres/covariance_impl.cc
|
||||
internal/ceres/dense_normal_cholesky_solver.cc
|
||||
internal/ceres/dense_qr_solver.cc
|
||||
internal/ceres/dense_sparse_matrix.cc
|
||||
internal/ceres/detect_structure.cc
|
||||
internal/ceres/dogleg_strategy.cc
|
||||
internal/ceres/dynamic_compressed_row_jacobian_writer.cc
|
||||
internal/ceres/dynamic_compressed_row_sparse_matrix.cc
|
||||
internal/ceres/evaluator.cc
|
||||
internal/ceres/file.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_d_d_d.cc
|
||||
internal/ceres/generated/schur_eliminator_d_d_d.cc
|
||||
internal/ceres/gradient_checker.cc
|
||||
internal/ceres/gradient_checking_cost_function.cc
|
||||
internal/ceres/gradient_problem.cc
|
||||
internal/ceres/gradient_problem_solver.cc
|
||||
internal/ceres/implicit_schur_complement.cc
|
||||
internal/ceres/is_close.cc
|
||||
internal/ceres/iterative_schur_complement_solver.cc
|
||||
internal/ceres/lapack.cc
|
||||
internal/ceres/levenberg_marquardt_strategy.cc
|
||||
internal/ceres/linear_least_squares_problems.cc
|
||||
internal/ceres/linear_operator.cc
|
||||
internal/ceres/linear_solver.cc
|
||||
internal/ceres/line_search.cc
|
||||
internal/ceres/line_search_direction.cc
|
||||
internal/ceres/line_search_minimizer.cc
|
||||
internal/ceres/line_search_preprocessor.cc
|
||||
internal/ceres/local_parameterization.cc
|
||||
internal/ceres/loss_function.cc
|
||||
internal/ceres/low_rank_inverse_hessian.cc
|
||||
internal/ceres/minimizer.cc
|
||||
internal/ceres/normal_prior.cc
|
||||
internal/ceres/parameter_block_ordering.cc
|
||||
internal/ceres/partitioned_matrix_view.cc
|
||||
internal/ceres/polynomial.cc
|
||||
internal/ceres/preconditioner.cc
|
||||
internal/ceres/preprocessor.cc
|
||||
internal/ceres/problem.cc
|
||||
internal/ceres/problem_impl.cc
|
||||
internal/ceres/program.cc
|
||||
internal/ceres/reorder_program.cc
|
||||
internal/ceres/residual_block.cc
|
||||
internal/ceres/residual_block_utils.cc
|
||||
internal/ceres/schur_complement_solver.cc
|
||||
internal/ceres/schur_eliminator.cc
|
||||
internal/ceres/schur_jacobi_preconditioner.cc
|
||||
internal/ceres/scratch_evaluate_preparer.cc
|
||||
internal/ceres/solver.cc
|
||||
internal/ceres/solver_utils.cc
|
||||
internal/ceres/sparse_matrix.cc
|
||||
internal/ceres/sparse_normal_cholesky_solver.cc
|
||||
internal/ceres/split.cc
|
||||
internal/ceres/stringprintf.cc
|
||||
internal/ceres/triplet_sparse_matrix.cc
|
||||
internal/ceres/trust_region_minimizer.cc
|
||||
internal/ceres/trust_region_preprocessor.cc
|
||||
internal/ceres/trust_region_step_evaluator.cc
|
||||
internal/ceres/trust_region_strategy.cc
|
||||
internal/ceres/types.cc
|
||||
internal/ceres/wall_time.cc
|
||||
internal/ceres/accelerate_sparse.cc
|
||||
internal/ceres/array_utils.cc
|
||||
internal/ceres/blas.cc
|
||||
internal/ceres/block_evaluate_preparer.cc
|
||||
internal/ceres/block_jacobian_writer.cc
|
||||
internal/ceres/block_jacobi_preconditioner.cc
|
||||
internal/ceres/block_random_access_dense_matrix.cc
|
||||
internal/ceres/block_random_access_diagonal_matrix.cc
|
||||
internal/ceres/block_random_access_matrix.cc
|
||||
internal/ceres/block_random_access_sparse_matrix.cc
|
||||
internal/ceres/block_sparse_matrix.cc
|
||||
internal/ceres/block_structure.cc
|
||||
internal/ceres/callbacks.cc
|
||||
internal/ceres/canonical_views_clustering.cc
|
||||
internal/ceres/c_api.cc
|
||||
internal/ceres/cgnr_solver.cc
|
||||
internal/ceres/compressed_col_sparse_matrix_utils.cc
|
||||
internal/ceres/compressed_row_jacobian_writer.cc
|
||||
internal/ceres/compressed_row_sparse_matrix.cc
|
||||
internal/ceres/conditioned_cost_function.cc
|
||||
internal/ceres/conjugate_gradients_solver.cc
|
||||
internal/ceres/context.cc
|
||||
internal/ceres/context_impl.cc
|
||||
internal/ceres/coordinate_descent_minimizer.cc
|
||||
internal/ceres/corrector.cc
|
||||
internal/ceres/covariance.cc
|
||||
internal/ceres/covariance_impl.cc
|
||||
internal/ceres/cxsparse.cc
|
||||
internal/ceres/dense_normal_cholesky_solver.cc
|
||||
internal/ceres/dense_qr_solver.cc
|
||||
internal/ceres/dense_sparse_matrix.cc
|
||||
internal/ceres/detect_structure.cc
|
||||
internal/ceres/dogleg_strategy.cc
|
||||
internal/ceres/dynamic_compressed_row_jacobian_writer.cc
|
||||
internal/ceres/dynamic_compressed_row_sparse_matrix.cc
|
||||
internal/ceres/dynamic_sparse_normal_cholesky_solver.cc
|
||||
internal/ceres/eigensparse.cc
|
||||
internal/ceres/evaluator.cc
|
||||
internal/ceres/file.cc
|
||||
internal/ceres/float_cxsparse.cc
|
||||
internal/ceres/float_suitesparse.cc
|
||||
internal/ceres/function_sample.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_d_d_d.cc
|
||||
internal/ceres/generated/schur_eliminator_d_d_d.cc
|
||||
internal/ceres/gradient_checker.cc
|
||||
internal/ceres/gradient_checking_cost_function.cc
|
||||
internal/ceres/gradient_problem.cc
|
||||
internal/ceres/gradient_problem_solver.cc
|
||||
internal/ceres/implicit_schur_complement.cc
|
||||
internal/ceres/inner_product_computer.cc
|
||||
internal/ceres/is_close.cc
|
||||
internal/ceres/iterative_refiner.cc
|
||||
internal/ceres/iterative_schur_complement_solver.cc
|
||||
internal/ceres/lapack.cc
|
||||
internal/ceres/levenberg_marquardt_strategy.cc
|
||||
internal/ceres/linear_least_squares_problems.cc
|
||||
internal/ceres/linear_operator.cc
|
||||
internal/ceres/linear_solver.cc
|
||||
internal/ceres/line_search.cc
|
||||
internal/ceres/line_search_direction.cc
|
||||
internal/ceres/line_search_minimizer.cc
|
||||
internal/ceres/line_search_preprocessor.cc
|
||||
internal/ceres/local_parameterization.cc
|
||||
internal/ceres/loss_function.cc
|
||||
internal/ceres/low_rank_inverse_hessian.cc
|
||||
internal/ceres/minimizer.cc
|
||||
internal/ceres/normal_prior.cc
|
||||
internal/ceres/parallel_for_cxx.cc
|
||||
internal/ceres/parallel_for_nothreads.cc
|
||||
internal/ceres/parallel_for_openmp.cc
|
||||
internal/ceres/parallel_utils.cc
|
||||
internal/ceres/parameter_block_ordering.cc
|
||||
internal/ceres/partitioned_matrix_view.cc
|
||||
internal/ceres/polynomial.cc
|
||||
internal/ceres/preconditioner.cc
|
||||
internal/ceres/preprocessor.cc
|
||||
internal/ceres/problem.cc
|
||||
internal/ceres/problem_impl.cc
|
||||
internal/ceres/program.cc
|
||||
internal/ceres/reorder_program.cc
|
||||
internal/ceres/residual_block.cc
|
||||
internal/ceres/residual_block_utils.cc
|
||||
internal/ceres/schur_complement_solver.cc
|
||||
internal/ceres/schur_eliminator.cc
|
||||
internal/ceres/schur_jacobi_preconditioner.cc
|
||||
internal/ceres/schur_templates.cc
|
||||
internal/ceres/scratch_evaluate_preparer.cc
|
||||
internal/ceres/single_linkage_clustering.cc
|
||||
internal/ceres/solver.cc
|
||||
internal/ceres/solver_utils.cc
|
||||
internal/ceres/sparse_cholesky.cc
|
||||
internal/ceres/sparse_matrix.cc
|
||||
internal/ceres/sparse_normal_cholesky_solver.cc
|
||||
internal/ceres/split.cc
|
||||
internal/ceres/stringprintf.cc
|
||||
internal/ceres/subset_preconditioner.cc
|
||||
internal/ceres/suitesparse.cc
|
||||
internal/ceres/thread_pool.cc
|
||||
internal/ceres/thread_token_provider.cc
|
||||
internal/ceres/triplet_sparse_matrix.cc
|
||||
internal/ceres/trust_region_minimizer.cc
|
||||
internal/ceres/trust_region_preprocessor.cc
|
||||
internal/ceres/trust_region_step_evaluator.cc
|
||||
internal/ceres/trust_region_strategy.cc
|
||||
internal/ceres/types.cc
|
||||
internal/ceres/visibility_based_preconditioner.cc
|
||||
internal/ceres/visibility.cc
|
||||
internal/ceres/wall_time.cc
|
||||
|
||||
include/ceres/autodiff_cost_function.h
|
||||
include/ceres/autodiff_local_parameterization.h
|
||||
include/ceres/c_api.h
|
||||
include/ceres/ceres.h
|
||||
include/ceres/conditioned_cost_function.h
|
||||
include/ceres/cost_function.h
|
||||
include/ceres/cost_function_to_functor.h
|
||||
include/ceres/covariance.h
|
||||
include/ceres/crs_matrix.h
|
||||
include/ceres/dynamic_autodiff_cost_function.h
|
||||
include/ceres/dynamic_cost_function_to_functor.h
|
||||
include/ceres/dynamic_numeric_diff_cost_function.h
|
||||
include/ceres/fpclassify.h
|
||||
include/ceres/gradient_checker.h
|
||||
include/ceres/gradient_problem.h
|
||||
include/ceres/gradient_problem_solver.h
|
||||
include/ceres/internal/autodiff.h
|
||||
include/ceres/internal/disable_warnings.h
|
||||
include/ceres/internal/eigen.h
|
||||
include/ceres/internal/fixed_array.h
|
||||
include/ceres/internal/macros.h
|
||||
include/ceres/internal/manual_constructor.h
|
||||
include/ceres/internal/numeric_diff.h
|
||||
include/ceres/internal/port.h
|
||||
include/ceres/internal/reenable_warnings.h
|
||||
include/ceres/internal/scoped_ptr.h
|
||||
include/ceres/internal/variadic_evaluate.h
|
||||
include/ceres/iteration_callback.h
|
||||
include/ceres/jet.h
|
||||
include/ceres/local_parameterization.h
|
||||
include/ceres/loss_function.h
|
||||
include/ceres/normal_prior.h
|
||||
include/ceres/numeric_diff_cost_function.h
|
||||
include/ceres/numeric_diff_options.h
|
||||
include/ceres/ordered_groups.h
|
||||
include/ceres/problem.h
|
||||
include/ceres/rotation.h
|
||||
include/ceres/sized_cost_function.h
|
||||
include/ceres/solver.h
|
||||
include/ceres/types.h
|
||||
include/ceres/version.h
|
||||
internal/ceres/array_utils.h
|
||||
internal/ceres/blas.h
|
||||
internal/ceres/block_evaluate_preparer.h
|
||||
internal/ceres/block_jacobian_writer.h
|
||||
internal/ceres/block_jacobi_preconditioner.h
|
||||
internal/ceres/block_random_access_dense_matrix.h
|
||||
internal/ceres/block_random_access_diagonal_matrix.h
|
||||
internal/ceres/block_random_access_matrix.h
|
||||
internal/ceres/block_random_access_sparse_matrix.h
|
||||
internal/ceres/block_sparse_matrix.h
|
||||
internal/ceres/block_structure.h
|
||||
internal/ceres/callbacks.h
|
||||
internal/ceres/casts.h
|
||||
internal/ceres/cgnr_linear_operator.h
|
||||
internal/ceres/cgnr_solver.h
|
||||
internal/ceres/collections_port.h
|
||||
internal/ceres/compressed_col_sparse_matrix_utils.h
|
||||
internal/ceres/compressed_row_jacobian_writer.h
|
||||
internal/ceres/compressed_row_sparse_matrix.h
|
||||
internal/ceres/conjugate_gradients_solver.h
|
||||
internal/ceres/coordinate_descent_minimizer.h
|
||||
internal/ceres/corrector.h
|
||||
internal/ceres/covariance_impl.h
|
||||
internal/ceres/cxsparse.h
|
||||
internal/ceres/dense_jacobian_writer.h
|
||||
internal/ceres/dense_normal_cholesky_solver.h
|
||||
internal/ceres/dense_qr_solver.h
|
||||
internal/ceres/dense_sparse_matrix.h
|
||||
internal/ceres/detect_structure.h
|
||||
internal/ceres/dogleg_strategy.h
|
||||
internal/ceres/dynamic_compressed_row_finalizer.h
|
||||
internal/ceres/dynamic_compressed_row_jacobian_writer.h
|
||||
internal/ceres/dynamic_compressed_row_sparse_matrix.h
|
||||
internal/ceres/evaluator.h
|
||||
internal/ceres/execution_summary.h
|
||||
internal/ceres/file.h
|
||||
internal/ceres/gradient_checking_cost_function.h
|
||||
internal/ceres/gradient_problem_evaluator.h
|
||||
internal/ceres/graph_algorithms.h
|
||||
internal/ceres/graph.h
|
||||
internal/ceres/householder_vector.h
|
||||
internal/ceres/implicit_schur_complement.h
|
||||
internal/ceres/integral_types.h
|
||||
internal/ceres/is_close.h
|
||||
internal/ceres/iterative_schur_complement_solver.h
|
||||
internal/ceres/lapack.h
|
||||
internal/ceres/levenberg_marquardt_strategy.h
|
||||
internal/ceres/linear_least_squares_problems.h
|
||||
internal/ceres/linear_operator.h
|
||||
internal/ceres/linear_solver.h
|
||||
internal/ceres/line_search_direction.h
|
||||
internal/ceres/line_search.h
|
||||
internal/ceres/line_search_minimizer.h
|
||||
internal/ceres/line_search_preprocessor.h
|
||||
internal/ceres/low_rank_inverse_hessian.h
|
||||
internal/ceres/map_util.h
|
||||
internal/ceres/minimizer.h
|
||||
internal/ceres/mutex.h
|
||||
internal/ceres/parameter_block.h
|
||||
internal/ceres/parameter_block_ordering.h
|
||||
internal/ceres/partitioned_matrix_view.h
|
||||
internal/ceres/partitioned_matrix_view_impl.h
|
||||
internal/ceres/polynomial.h
|
||||
internal/ceres/preconditioner.h
|
||||
internal/ceres/preprocessor.h
|
||||
internal/ceres/problem_impl.h
|
||||
internal/ceres/program_evaluator.h
|
||||
internal/ceres/program.h
|
||||
internal/ceres/random.h
|
||||
internal/ceres/reorder_program.h
|
||||
internal/ceres/residual_block.h
|
||||
internal/ceres/residual_block_utils.h
|
||||
internal/ceres/schur_complement_solver.h
|
||||
internal/ceres/schur_eliminator.h
|
||||
internal/ceres/schur_eliminator_impl.h
|
||||
internal/ceres/schur_jacobi_preconditioner.h
|
||||
internal/ceres/scratch_evaluate_preparer.h
|
||||
internal/ceres/small_blas.h
|
||||
internal/ceres/solver_utils.h
|
||||
internal/ceres/sparse_matrix.h
|
||||
internal/ceres/sparse_normal_cholesky_solver.h
|
||||
internal/ceres/split.h
|
||||
internal/ceres/stl_util.h
|
||||
internal/ceres/stringprintf.h
|
||||
internal/ceres/suitesparse.h
|
||||
internal/ceres/triplet_sparse_matrix.h
|
||||
internal/ceres/trust_region_minimizer.h
|
||||
internal/ceres/trust_region_preprocessor.h
|
||||
internal/ceres/trust_region_step_evaluator.h
|
||||
internal/ceres/trust_region_strategy.h
|
||||
internal/ceres/visibility_based_preconditioner.h
|
||||
internal/ceres/wall_time.h
|
||||
include/ceres/autodiff_cost_function.h
|
||||
include/ceres/autodiff_first_order_function.h
|
||||
include/ceres/autodiff_local_parameterization.h
|
||||
include/ceres/c_api.h
|
||||
include/ceres/ceres.h
|
||||
include/ceres/conditioned_cost_function.h
|
||||
include/ceres/context.h
|
||||
include/ceres/cost_function.h
|
||||
include/ceres/cost_function_to_functor.h
|
||||
include/ceres/covariance.h
|
||||
include/ceres/crs_matrix.h
|
||||
include/ceres/cubic_interpolation.h
|
||||
include/ceres/dynamic_autodiff_cost_function.h
|
||||
include/ceres/dynamic_cost_function.h
|
||||
include/ceres/dynamic_cost_function_to_functor.h
|
||||
include/ceres/dynamic_numeric_diff_cost_function.h
|
||||
include/ceres/evaluation_callback.h
|
||||
include/ceres/first_order_function.h
|
||||
include/ceres/gradient_checker.h
|
||||
include/ceres/gradient_problem.h
|
||||
include/ceres/gradient_problem_solver.h
|
||||
include/ceres/internal/array_selector.h
|
||||
include/ceres/internal/autodiff.h
|
||||
include/ceres/internal/disable_warnings.h
|
||||
include/ceres/internal/eigen.h
|
||||
include/ceres/internal/fixed_array.h
|
||||
include/ceres/internal/householder_vector.h
|
||||
include/ceres/internal/integer_sequence_algorithm.h
|
||||
include/ceres/internal/line_parameterization.h
|
||||
include/ceres/internal/memory.h
|
||||
include/ceres/internal/numeric_diff.h
|
||||
include/ceres/internal/parameter_dims.h
|
||||
include/ceres/internal/port.h
|
||||
include/ceres/internal/reenable_warnings.h
|
||||
include/ceres/internal/variadic_evaluate.h
|
||||
include/ceres/iteration_callback.h
|
||||
include/ceres/jet.h
|
||||
include/ceres/local_parameterization.h
|
||||
include/ceres/loss_function.h
|
||||
include/ceres/normal_prior.h
|
||||
include/ceres/numeric_diff_cost_function.h
|
||||
include/ceres/numeric_diff_options.h
|
||||
include/ceres/ordered_groups.h
|
||||
include/ceres/problem.h
|
||||
include/ceres/rotation.h
|
||||
include/ceres/sized_cost_function.h
|
||||
include/ceres/solver.h
|
||||
include/ceres/tiny_solver_autodiff_function.h
|
||||
include/ceres/tiny_solver_cost_function_adapter.h
|
||||
include/ceres/tiny_solver.h
|
||||
include/ceres/types.h
|
||||
include/ceres/version.h
|
||||
internal/ceres/accelerate_sparse.h
|
||||
internal/ceres/array_utils.h
|
||||
internal/ceres/blas.h
|
||||
internal/ceres/block_evaluate_preparer.h
|
||||
internal/ceres/block_jacobian_writer.h
|
||||
internal/ceres/block_jacobi_preconditioner.h
|
||||
internal/ceres/block_random_access_dense_matrix.h
|
||||
internal/ceres/block_random_access_diagonal_matrix.h
|
||||
internal/ceres/block_random_access_matrix.h
|
||||
internal/ceres/block_random_access_sparse_matrix.h
|
||||
internal/ceres/block_sparse_matrix.h
|
||||
internal/ceres/block_structure.h
|
||||
internal/ceres/callbacks.h
|
||||
internal/ceres/canonical_views_clustering.h
|
||||
internal/ceres/casts.h
|
||||
internal/ceres/cgnr_linear_operator.h
|
||||
internal/ceres/cgnr_solver.h
|
||||
internal/ceres/compressed_col_sparse_matrix_utils.h
|
||||
internal/ceres/compressed_row_jacobian_writer.h
|
||||
internal/ceres/compressed_row_sparse_matrix.h
|
||||
internal/ceres/concurrent_queue.h
|
||||
internal/ceres/conjugate_gradients_solver.h
|
||||
internal/ceres/context_impl.h
|
||||
internal/ceres/coordinate_descent_minimizer.h
|
||||
internal/ceres/corrector.h
|
||||
internal/ceres/covariance_impl.h
|
||||
internal/ceres/cxsparse.h
|
||||
internal/ceres/dense_jacobian_writer.h
|
||||
internal/ceres/dense_normal_cholesky_solver.h
|
||||
internal/ceres/dense_qr_solver.h
|
||||
internal/ceres/dense_sparse_matrix.h
|
||||
internal/ceres/detect_structure.h
|
||||
internal/ceres/dogleg_strategy.h
|
||||
internal/ceres/dynamic_compressed_row_finalizer.h
|
||||
internal/ceres/dynamic_compressed_row_jacobian_writer.h
|
||||
internal/ceres/dynamic_compressed_row_sparse_matrix.h
|
||||
internal/ceres/dynamic_sparse_normal_cholesky_solver.h
|
||||
internal/ceres/eigensparse.h
|
||||
internal/ceres/evaluator.h
|
||||
internal/ceres/execution_summary.h
|
||||
internal/ceres/file.h
|
||||
internal/ceres/float_cxsparse.h
|
||||
internal/ceres/float_suitesparse.h
|
||||
internal/ceres/function_sample.h
|
||||
internal/ceres/gradient_checking_cost_function.h
|
||||
internal/ceres/gradient_problem_evaluator.h
|
||||
internal/ceres/graph_algorithms.h
|
||||
internal/ceres/graph.h
|
||||
internal/ceres/implicit_schur_complement.h
|
||||
internal/ceres/inner_product_computer.h
|
||||
internal/ceres/invert_psd_matrix.h
|
||||
internal/ceres/is_close.h
|
||||
internal/ceres/iterative_refiner.h
|
||||
internal/ceres/iterative_schur_complement_solver.h
|
||||
internal/ceres/lapack.h
|
||||
internal/ceres/levenberg_marquardt_strategy.h
|
||||
internal/ceres/linear_least_squares_problems.h
|
||||
internal/ceres/linear_operator.h
|
||||
internal/ceres/linear_solver.h
|
||||
internal/ceres/line_search_direction.h
|
||||
internal/ceres/line_search.h
|
||||
internal/ceres/line_search_minimizer.h
|
||||
internal/ceres/line_search_preprocessor.h
|
||||
internal/ceres/low_rank_inverse_hessian.h
|
||||
internal/ceres/map_util.h
|
||||
internal/ceres/minimizer.h
|
||||
internal/ceres/pair_hash.h
|
||||
internal/ceres/parallel_for.h
|
||||
internal/ceres/parallel_utils.h
|
||||
internal/ceres/parameter_block.h
|
||||
internal/ceres/parameter_block_ordering.h
|
||||
internal/ceres/partitioned_matrix_view.h
|
||||
internal/ceres/partitioned_matrix_view_impl.h
|
||||
internal/ceres/polynomial.h
|
||||
internal/ceres/preconditioner.h
|
||||
internal/ceres/preprocessor.h
|
||||
internal/ceres/problem_impl.h
|
||||
internal/ceres/program_evaluator.h
|
||||
internal/ceres/program.h
|
||||
internal/ceres/random.h
|
||||
internal/ceres/reorder_program.h
|
||||
internal/ceres/residual_block.h
|
||||
internal/ceres/residual_block_utils.h
|
||||
internal/ceres/schur_complement_solver.h
|
||||
internal/ceres/schur_eliminator.h
|
||||
internal/ceres/schur_eliminator_impl.h
|
||||
internal/ceres/schur_jacobi_preconditioner.h
|
||||
internal/ceres/schur_templates.h
|
||||
internal/ceres/scoped_thread_token.h
|
||||
internal/ceres/scratch_evaluate_preparer.h
|
||||
internal/ceres/single_linkage_clustering.h
|
||||
internal/ceres/small_blas_generic.h
|
||||
internal/ceres/small_blas.h
|
||||
internal/ceres/solver_utils.h
|
||||
internal/ceres/sparse_cholesky.h
|
||||
internal/ceres/sparse_matrix.h
|
||||
internal/ceres/sparse_normal_cholesky_solver.h
|
||||
internal/ceres/split.h
|
||||
internal/ceres/stl_util.h
|
||||
internal/ceres/stringprintf.h
|
||||
internal/ceres/subset_preconditioner.h
|
||||
internal/ceres/suitesparse.h
|
||||
internal/ceres/thread_pool.h
|
||||
internal/ceres/thread_token_provider.h
|
||||
internal/ceres/triplet_sparse_matrix.h
|
||||
internal/ceres/trust_region_minimizer.h
|
||||
internal/ceres/trust_region_preprocessor.h
|
||||
internal/ceres/trust_region_step_evaluator.h
|
||||
internal/ceres/trust_region_strategy.h
|
||||
internal/ceres/visibility_based_preconditioner.h
|
||||
internal/ceres/visibility.h
|
||||
internal/ceres/wall_time.h
|
||||
)
|
||||
|
||||
set(LIB
|
||||
@@ -263,44 +319,48 @@ set(LIB
|
||||
|
||||
if(WITH_LIBMV_SCHUR_SPECIALIZATIONS)
|
||||
list(APPEND SRC
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_2.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_4.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_4.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_6.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_9.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_4.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_8.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_9.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_d_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_2.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_4.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_2_2.cc
|
||||
internal/ceres/generated/schur_eliminator_2_2_3.cc
|
||||
internal/ceres/generated/schur_eliminator_2_2_4.cc
|
||||
internal/ceres/generated/schur_eliminator_2_2_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_3.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_4.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_6.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_9.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_3.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_4.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_8.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_9.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_d_d.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_2.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_3.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_4.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_2.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_4.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_4.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_6.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_9.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_4.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_6.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_8.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_9.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_d_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_3_3_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_2.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_4.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_2_2.cc
|
||||
internal/ceres/generated/schur_eliminator_2_2_3.cc
|
||||
internal/ceres/generated/schur_eliminator_2_2_4.cc
|
||||
internal/ceres/generated/schur_eliminator_2_2_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_3.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_4.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_6.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_9.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_3.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_4.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_6.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_8.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_9.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_d_d.cc
|
||||
internal/ceres/generated/schur_eliminator_3_3_3.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_2.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_3.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_4.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_d.cc
|
||||
)
|
||||
else()
|
||||
add_definitions(-DCERES_RESTRICT_SCHUR_SPECIALIZATION)
|
||||
@@ -315,13 +375,9 @@ add_definitions(
|
||||
-DCERES_NO_SUITESPARSE
|
||||
-DCERES_NO_CXSPARSE
|
||||
-DCERES_NO_LAPACK
|
||||
-DCERES_NO_ACCELERATE_SPARSE
|
||||
-DCERES_HAVE_RWLOCK
|
||||
-DCERES_USE_CXX_THREADS
|
||||
)
|
||||
|
||||
if(WITH_OPENMP)
|
||||
add_definitions(
|
||||
-DCERES_USE_OPENMP
|
||||
)
|
||||
endif()
|
||||
|
||||
blender_add_lib(extern_ceres "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
1095
extern/ceres/ChangeLog
vendored
1095
extern/ceres/ChangeLog
vendored
File diff suppressed because it is too large
Load Diff
9
extern/ceres/bundle.sh
vendored
9
extern/ceres/bundle.sh
vendored
@@ -9,7 +9,6 @@ fi
|
||||
|
||||
repo="https://ceres-solver.googlesource.com/ceres-solver"
|
||||
branch="master"
|
||||
#tag="1.4.0"
|
||||
tag=""
|
||||
tmp=`mktemp -d`
|
||||
checkout="$tmp/ceres"
|
||||
@@ -157,14 +156,10 @@ add_definitions(
|
||||
-DCERES_NO_SUITESPARSE
|
||||
-DCERES_NO_CXSPARSE
|
||||
-DCERES_NO_LAPACK
|
||||
-DCERES_NO_ACCELERATE_SPARSE
|
||||
-DCERES_HAVE_RWLOCK
|
||||
-DCERES_USE_CXX_THREADS
|
||||
)
|
||||
|
||||
if(WITH_OPENMP)
|
||||
add_definitions(
|
||||
-DCERES_USE_OPENMP
|
||||
)
|
||||
endif()
|
||||
|
||||
blender_add_lib(extern_ceres "\${SRC}" "\${INC}" "\${INC_SYS}" "\${LIB}")
|
||||
EOF
|
||||
|
81
extern/ceres/files.txt
vendored
81
extern/ceres/files.txt
vendored
@@ -1,29 +1,37 @@
|
||||
include/ceres/autodiff_cost_function.h
|
||||
include/ceres/autodiff_first_order_function.h
|
||||
include/ceres/autodiff_local_parameterization.h
|
||||
include/ceres/c_api.h
|
||||
include/ceres/ceres.h
|
||||
include/ceres/conditioned_cost_function.h
|
||||
include/ceres/context.h
|
||||
include/ceres/cost_function.h
|
||||
include/ceres/cost_function_to_functor.h
|
||||
include/ceres/covariance.h
|
||||
include/ceres/crs_matrix.h
|
||||
include/ceres/cubic_interpolation.h
|
||||
include/ceres/dynamic_autodiff_cost_function.h
|
||||
include/ceres/dynamic_cost_function.h
|
||||
include/ceres/dynamic_cost_function_to_functor.h
|
||||
include/ceres/dynamic_numeric_diff_cost_function.h
|
||||
include/ceres/fpclassify.h
|
||||
include/ceres/evaluation_callback.h
|
||||
include/ceres/first_order_function.h
|
||||
include/ceres/gradient_checker.h
|
||||
include/ceres/gradient_problem.h
|
||||
include/ceres/gradient_problem_solver.h
|
||||
include/ceres/internal/array_selector.h
|
||||
include/ceres/internal/autodiff.h
|
||||
include/ceres/internal/disable_warnings.h
|
||||
include/ceres/internal/eigen.h
|
||||
include/ceres/internal/fixed_array.h
|
||||
include/ceres/internal/macros.h
|
||||
include/ceres/internal/manual_constructor.h
|
||||
include/ceres/internal/householder_vector.h
|
||||
include/ceres/internal/integer_sequence_algorithm.h
|
||||
include/ceres/internal/line_parameterization.h
|
||||
include/ceres/internal/memory.h
|
||||
include/ceres/internal/numeric_diff.h
|
||||
include/ceres/internal/parameter_dims.h
|
||||
include/ceres/internal/port.h
|
||||
include/ceres/internal/reenable_warnings.h
|
||||
include/ceres/internal/scoped_ptr.h
|
||||
include/ceres/internal/variadic_evaluate.h
|
||||
include/ceres/iteration_callback.h
|
||||
include/ceres/jet.h
|
||||
@@ -37,8 +45,13 @@ include/ceres/problem.h
|
||||
include/ceres/rotation.h
|
||||
include/ceres/sized_cost_function.h
|
||||
include/ceres/solver.h
|
||||
include/ceres/tiny_solver_autodiff_function.h
|
||||
include/ceres/tiny_solver_cost_function_adapter.h
|
||||
include/ceres/tiny_solver.h
|
||||
include/ceres/types.h
|
||||
include/ceres/version.h
|
||||
internal/ceres/accelerate_sparse.cc
|
||||
internal/ceres/accelerate_sparse.h
|
||||
internal/ceres/array_utils.cc
|
||||
internal/ceres/array_utils.h
|
||||
internal/ceres/blas.cc
|
||||
@@ -63,21 +76,26 @@ internal/ceres/block_structure.cc
|
||||
internal/ceres/block_structure.h
|
||||
internal/ceres/callbacks.cc
|
||||
internal/ceres/callbacks.h
|
||||
internal/ceres/canonical_views_clustering.cc
|
||||
internal/ceres/canonical_views_clustering.h
|
||||
internal/ceres/c_api.cc
|
||||
internal/ceres/casts.h
|
||||
internal/ceres/cgnr_linear_operator.h
|
||||
internal/ceres/cgnr_solver.cc
|
||||
internal/ceres/cgnr_solver.h
|
||||
internal/ceres/collections_port.h
|
||||
internal/ceres/compressed_col_sparse_matrix_utils.cc
|
||||
internal/ceres/compressed_col_sparse_matrix_utils.h
|
||||
internal/ceres/compressed_row_jacobian_writer.cc
|
||||
internal/ceres/compressed_row_jacobian_writer.h
|
||||
internal/ceres/compressed_row_sparse_matrix.cc
|
||||
internal/ceres/compressed_row_sparse_matrix.h
|
||||
internal/ceres/concurrent_queue.h
|
||||
internal/ceres/conditioned_cost_function.cc
|
||||
internal/ceres/conjugate_gradients_solver.cc
|
||||
internal/ceres/conjugate_gradients_solver.h
|
||||
internal/ceres/context.cc
|
||||
internal/ceres/context_impl.cc
|
||||
internal/ceres/context_impl.h
|
||||
internal/ceres/coordinate_descent_minimizer.cc
|
||||
internal/ceres/coordinate_descent_minimizer.h
|
||||
internal/ceres/corrector.cc
|
||||
@@ -85,6 +103,7 @@ internal/ceres/corrector.h
|
||||
internal/ceres/covariance.cc
|
||||
internal/ceres/covariance_impl.cc
|
||||
internal/ceres/covariance_impl.h
|
||||
internal/ceres/cxsparse.cc
|
||||
internal/ceres/cxsparse.h
|
||||
internal/ceres/dense_jacobian_writer.h
|
||||
internal/ceres/dense_normal_cholesky_solver.cc
|
||||
@@ -102,11 +121,21 @@ internal/ceres/dynamic_compressed_row_jacobian_writer.cc
|
||||
internal/ceres/dynamic_compressed_row_jacobian_writer.h
|
||||
internal/ceres/dynamic_compressed_row_sparse_matrix.cc
|
||||
internal/ceres/dynamic_compressed_row_sparse_matrix.h
|
||||
internal/ceres/dynamic_sparse_normal_cholesky_solver.cc
|
||||
internal/ceres/dynamic_sparse_normal_cholesky_solver.h
|
||||
internal/ceres/eigensparse.cc
|
||||
internal/ceres/eigensparse.h
|
||||
internal/ceres/evaluator.cc
|
||||
internal/ceres/evaluator.h
|
||||
internal/ceres/execution_summary.h
|
||||
internal/ceres/file.cc
|
||||
internal/ceres/file.h
|
||||
internal/ceres/float_cxsparse.cc
|
||||
internal/ceres/float_cxsparse.h
|
||||
internal/ceres/float_suitesparse.cc
|
||||
internal/ceres/float_suitesparse.h
|
||||
internal/ceres/function_sample.cc
|
||||
internal/ceres/function_sample.h
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_2.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_2_4.cc
|
||||
@@ -118,10 +147,12 @@ internal/ceres/generated/partitioned_matrix_view_2_3_9.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_3_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_4.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_6.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_8.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_9.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_4_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_2_d_d.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_3_3_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_2.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_3.cc
|
||||
internal/ceres/generated/partitioned_matrix_view_4_4_4.cc
|
||||
@@ -138,17 +169,18 @@ internal/ceres/generated/schur_eliminator_2_3_9.cc
|
||||
internal/ceres/generated/schur_eliminator_2_3_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_3.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_4.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_6.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_8.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_9.cc
|
||||
internal/ceres/generated/schur_eliminator_2_4_d.cc
|
||||
internal/ceres/generated/schur_eliminator_2_d_d.cc
|
||||
internal/ceres/generated/schur_eliminator_3_3_3.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_2.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_3.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_4.cc
|
||||
internal/ceres/generated/schur_eliminator_4_4_d.cc
|
||||
internal/ceres/generated/schur_eliminator_d_d_d.cc
|
||||
internal/ceres/generate_eliminator_specialization.py
|
||||
internal/ceres/generate_partitioned_matrix_view_specializations.py
|
||||
internal/ceres/generate_template_specializations.py
|
||||
internal/ceres/gradient_checker.cc
|
||||
internal/ceres/gradient_checking_cost_function.cc
|
||||
internal/ceres/gradient_checking_cost_function.h
|
||||
@@ -157,12 +189,15 @@ internal/ceres/gradient_problem_evaluator.h
|
||||
internal/ceres/gradient_problem_solver.cc
|
||||
internal/ceres/graph_algorithms.h
|
||||
internal/ceres/graph.h
|
||||
internal/ceres/householder_vector.h
|
||||
internal/ceres/implicit_schur_complement.cc
|
||||
internal/ceres/implicit_schur_complement.h
|
||||
internal/ceres/integral_types.h
|
||||
internal/ceres/inner_product_computer.cc
|
||||
internal/ceres/inner_product_computer.h
|
||||
internal/ceres/invert_psd_matrix.h
|
||||
internal/ceres/is_close.cc
|
||||
internal/ceres/is_close.h
|
||||
internal/ceres/iterative_refiner.cc
|
||||
internal/ceres/iterative_refiner.h
|
||||
internal/ceres/iterative_schur_complement_solver.cc
|
||||
internal/ceres/iterative_schur_complement_solver.h
|
||||
internal/ceres/lapack.cc
|
||||
@@ -190,14 +225,21 @@ internal/ceres/low_rank_inverse_hessian.h
|
||||
internal/ceres/map_util.h
|
||||
internal/ceres/minimizer.cc
|
||||
internal/ceres/minimizer.h
|
||||
internal/ceres/mutex.h
|
||||
internal/ceres/normal_prior.cc
|
||||
internal/ceres/pair_hash.h
|
||||
internal/ceres/parallel_for_cxx.cc
|
||||
internal/ceres/parallel_for.h
|
||||
internal/ceres/parallel_for_nothreads.cc
|
||||
internal/ceres/parallel_for_openmp.cc
|
||||
internal/ceres/parallel_utils.cc
|
||||
internal/ceres/parallel_utils.h
|
||||
internal/ceres/parameter_block.h
|
||||
internal/ceres/parameter_block_ordering.cc
|
||||
internal/ceres/parameter_block_ordering.h
|
||||
internal/ceres/partitioned_matrix_view.cc
|
||||
internal/ceres/partitioned_matrix_view.h
|
||||
internal/ceres/partitioned_matrix_view_impl.h
|
||||
internal/ceres/partitioned_matrix_view_template.py
|
||||
internal/ceres/polynomial.cc
|
||||
internal/ceres/polynomial.h
|
||||
internal/ceres/preconditioner.cc
|
||||
@@ -222,14 +264,23 @@ internal/ceres/schur_complement_solver.h
|
||||
internal/ceres/schur_eliminator.cc
|
||||
internal/ceres/schur_eliminator.h
|
||||
internal/ceres/schur_eliminator_impl.h
|
||||
internal/ceres/schur_eliminator_template.py
|
||||
internal/ceres/schur_jacobi_preconditioner.cc
|
||||
internal/ceres/schur_jacobi_preconditioner.h
|
||||
internal/ceres/schur_templates.cc
|
||||
internal/ceres/schur_templates.h
|
||||
internal/ceres/scoped_thread_token.h
|
||||
internal/ceres/scratch_evaluate_preparer.cc
|
||||
internal/ceres/scratch_evaluate_preparer.h
|
||||
internal/ceres/single_linkage_clustering.cc
|
||||
internal/ceres/single_linkage_clustering.h
|
||||
internal/ceres/small_blas_generic.h
|
||||
internal/ceres/small_blas.h
|
||||
internal/ceres/solver.cc
|
||||
internal/ceres/solver_utils.cc
|
||||
internal/ceres/solver_utils.h
|
||||
internal/ceres/sparse_cholesky.cc
|
||||
internal/ceres/sparse_cholesky.h
|
||||
internal/ceres/sparse_matrix.cc
|
||||
internal/ceres/sparse_matrix.h
|
||||
internal/ceres/sparse_normal_cholesky_solver.cc
|
||||
@@ -239,7 +290,14 @@ internal/ceres/split.h
|
||||
internal/ceres/stl_util.h
|
||||
internal/ceres/stringprintf.cc
|
||||
internal/ceres/stringprintf.h
|
||||
internal/ceres/subset_preconditioner.cc
|
||||
internal/ceres/subset_preconditioner.h
|
||||
internal/ceres/suitesparse.cc
|
||||
internal/ceres/suitesparse.h
|
||||
internal/ceres/thread_pool.cc
|
||||
internal/ceres/thread_pool.h
|
||||
internal/ceres/thread_token_provider.cc
|
||||
internal/ceres/thread_token_provider.h
|
||||
internal/ceres/triplet_sparse_matrix.cc
|
||||
internal/ceres/triplet_sparse_matrix.h
|
||||
internal/ceres/trust_region_minimizer.cc
|
||||
@@ -251,7 +309,10 @@ internal/ceres/trust_region_step_evaluator.h
|
||||
internal/ceres/trust_region_strategy.cc
|
||||
internal/ceres/trust_region_strategy.h
|
||||
internal/ceres/types.cc
|
||||
internal/ceres/visibility_based_preconditioner.cc
|
||||
internal/ceres/visibility_based_preconditioner.h
|
||||
internal/ceres/visibility.cc
|
||||
internal/ceres/visibility.h
|
||||
internal/ceres/wall_time.cc
|
||||
internal/ceres/wall_time.h
|
||||
config/ceres/internal/config.h
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,7 +30,7 @@
|
||||
//
|
||||
// Create CostFunctions as needed by the least squares framework, with
|
||||
// Jacobians computed via automatic differentiation. For more
|
||||
// information on automatic differentation, see the wikipedia article
|
||||
// information on automatic differentiation, see the wikipedia article
|
||||
// at http://en.wikipedia.org/wiki/Automatic_differentiation
|
||||
//
|
||||
// To get an auto differentiated cost function, you must define a class with a
|
||||
@@ -54,7 +54,7 @@
|
||||
// for a series of measurements, where there is an instance of the cost function
|
||||
// for each measurement k.
|
||||
//
|
||||
// The actual cost added to the total problem is e^2, or (k - x'k)^2; however,
|
||||
// The actual cost added to the total problem is e^2, or (k - x'y)^2; however,
|
||||
// the squaring is implicitly done by the optimization framework.
|
||||
//
|
||||
// To write an auto-differentiable cost function for the above model, first
|
||||
@@ -90,7 +90,7 @@
|
||||
// Dimension of x ---------------+ |
|
||||
// Dimension of y ------------------+
|
||||
//
|
||||
// In this example, there is usually an instance for each measumerent of k.
|
||||
// In this example, there is usually an instance for each measurement of k.
|
||||
//
|
||||
// In the instantiation above, the template parameters following
|
||||
// "MyScalarCostFunctor", "1, 2, 2", describe the functor as computing a
|
||||
@@ -110,12 +110,8 @@
|
||||
// Dimension of x ------------------------------------+ |
|
||||
// Dimension of y ---------------------------------------+
|
||||
//
|
||||
// The framework can currently accommodate cost functions of up to 10
|
||||
// independent variables, and there is no limit on the dimensionality
|
||||
// of each of them.
|
||||
//
|
||||
// WARNING #1: Since the functor will get instantiated with different types for
|
||||
// T, you must to convert from other numeric types to T before mixing
|
||||
// T, you must convert from other numeric types to T before mixing
|
||||
// computations with other variables of type T. In the example above, this is
|
||||
// seen where instead of using k_ directly, k_ is wrapped with T(k_).
|
||||
//
|
||||
@@ -129,8 +125,9 @@
|
||||
#ifndef CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
|
||||
#define CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ceres/internal/autodiff.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/sized_cost_function.h"
|
||||
#include "ceres/types.h"
|
||||
#include "glog/logging.h"
|
||||
@@ -138,7 +135,7 @@
|
||||
namespace ceres {
|
||||
|
||||
// A cost function which computes the derivative of the cost with respect to
|
||||
// the parameters (a.k.a. the jacobian) using an autodifferentiation framework.
|
||||
// the parameters (a.k.a. the jacobian) using an auto differentiation framework.
|
||||
// The first template argument is the functor object, described in the header
|
||||
// comment. The second argument is the dimension of the residual (or
|
||||
// ceres::DYNAMIC to indicate it will be set at runtime), and subsequent
|
||||
@@ -153,27 +150,15 @@ namespace ceres {
|
||||
// of residuals for a single autodiff cost function at runtime.
|
||||
template <typename CostFunctor,
|
||||
int kNumResiduals, // Number of residuals, or ceres::DYNAMIC.
|
||||
int N0, // Number of parameters in block 0.
|
||||
int N1 = 0, // Number of parameters in block 1.
|
||||
int N2 = 0, // Number of parameters in block 2.
|
||||
int N3 = 0, // Number of parameters in block 3.
|
||||
int N4 = 0, // Number of parameters in block 4.
|
||||
int N5 = 0, // Number of parameters in block 5.
|
||||
int N6 = 0, // Number of parameters in block 6.
|
||||
int N7 = 0, // Number of parameters in block 7.
|
||||
int N8 = 0, // Number of parameters in block 8.
|
||||
int N9 = 0> // Number of parameters in block 9.
|
||||
class AutoDiffCostFunction : public SizedCostFunction<kNumResiduals,
|
||||
N0, N1, N2, N3, N4,
|
||||
N5, N6, N7, N8, N9> {
|
||||
int... Ns> // Number of parameters in each parameter block.
|
||||
class AutoDiffCostFunction : public SizedCostFunction<kNumResiduals, Ns...> {
|
||||
public:
|
||||
// Takes ownership of functor. Uses the template-provided value for the
|
||||
// number of residuals ("kNumResiduals").
|
||||
explicit AutoDiffCostFunction(CostFunctor* functor)
|
||||
: functor_(functor) {
|
||||
CHECK_NE(kNumResiduals, DYNAMIC)
|
||||
<< "Can't run the fixed-size constructor if the "
|
||||
<< "number of residuals is set to ceres::DYNAMIC.";
|
||||
explicit AutoDiffCostFunction(CostFunctor* functor) : functor_(functor) {
|
||||
static_assert(kNumResiduals != DYNAMIC,
|
||||
"Can't run the fixed-size constructor if the number of "
|
||||
"residuals is set to ceres::DYNAMIC.");
|
||||
}
|
||||
|
||||
// Takes ownership of functor. Ignores the template-provided
|
||||
@@ -183,13 +168,10 @@ class AutoDiffCostFunction : public SizedCostFunction<kNumResiduals,
|
||||
// numbers of residuals at runtime.
|
||||
AutoDiffCostFunction(CostFunctor* functor, int num_residuals)
|
||||
: functor_(functor) {
|
||||
CHECK_EQ(kNumResiduals, DYNAMIC)
|
||||
<< "Can't run the dynamic-size constructor if the "
|
||||
<< "number of residuals is not ceres::DYNAMIC.";
|
||||
SizedCostFunction<kNumResiduals,
|
||||
N0, N1, N2, N3, N4,
|
||||
N5, N6, N7, N8, N9>
|
||||
::set_num_residuals(num_residuals);
|
||||
static_assert(kNumResiduals == DYNAMIC,
|
||||
"Can't run the dynamic-size constructor if the number of "
|
||||
"residuals is not ceres::DYNAMIC.");
|
||||
SizedCostFunction<kNumResiduals, Ns...>::set_num_residuals(num_residuals);
|
||||
}
|
||||
|
||||
virtual ~AutoDiffCostFunction() {}
|
||||
@@ -197,29 +179,28 @@ class AutoDiffCostFunction : public SizedCostFunction<kNumResiduals,
|
||||
// Implementation details follow; clients of the autodiff cost function should
|
||||
// not have to examine below here.
|
||||
//
|
||||
// To handle varardic cost functions, some template magic is needed. It's
|
||||
// To handle variadic cost functions, some template magic is needed. It's
|
||||
// mostly hidden inside autodiff.h.
|
||||
virtual bool Evaluate(double const* const* parameters,
|
||||
double* residuals,
|
||||
double** jacobians) const {
|
||||
bool Evaluate(double const* const* parameters,
|
||||
double* residuals,
|
||||
double** jacobians) const override {
|
||||
using ParameterDims =
|
||||
typename SizedCostFunction<kNumResiduals, Ns...>::ParameterDims;
|
||||
|
||||
if (!jacobians) {
|
||||
return internal::VariadicEvaluate<
|
||||
CostFunctor, double, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>
|
||||
::Call(*functor_, parameters, residuals);
|
||||
return internal::VariadicEvaluate<ParameterDims>(
|
||||
*functor_, parameters, residuals);
|
||||
}
|
||||
return internal::AutoDiff<CostFunctor, double,
|
||||
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Differentiate(
|
||||
*functor_,
|
||||
parameters,
|
||||
SizedCostFunction<kNumResiduals,
|
||||
N0, N1, N2, N3, N4,
|
||||
N5, N6, N7, N8, N9>::num_residuals(),
|
||||
residuals,
|
||||
jacobians);
|
||||
}
|
||||
return internal::AutoDifferentiate<kNumResiduals, ParameterDims>(
|
||||
*functor_,
|
||||
parameters,
|
||||
SizedCostFunction<kNumResiduals, Ns...>::num_residuals(),
|
||||
residuals,
|
||||
jacobians);
|
||||
};
|
||||
|
||||
private:
|
||||
internal::scoped_ptr<CostFunctor> functor_;
|
||||
std::unique_ptr<CostFunctor> functor_;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
151
extern/ceres/include/ceres/autodiff_first_order_function.h
vendored
Normal file
151
extern/ceres/include/ceres/autodiff_first_order_function.h
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
||||
|
||||
#ifndef CERES_PUBLIC_AUTODIFF_FIRST_ORDER_FUNCTION_H_
|
||||
#define CERES_PUBLIC_AUTODIFF_FIRST_ORDER_FUNCTION_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ceres/first_order_function.h"
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/internal/fixed_array.h"
|
||||
#include "ceres/jet.h"
|
||||
#include "ceres/types.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// Create FirstOrderFunctions as needed by the GradientProblem
|
||||
// framework, with gradients computed via automatic
|
||||
// differentiation. For more information on automatic differentiation,
|
||||
// see the wikipedia article at
|
||||
// http://en.wikipedia.org/wiki/Automatic_differentiation
|
||||
//
|
||||
// To get an auto differentiated function, you must define a class
|
||||
// with a templated operator() (a functor) that computes the cost
|
||||
// function in terms of the template parameter T. The autodiff
|
||||
// framework substitutes appropriate "jet" objects for T in order to
|
||||
// compute the derivative when necessary, but this is hidden, and you
|
||||
// should write the function as if T were a scalar type (e.g. a
|
||||
// double-precision floating point number).
|
||||
//
|
||||
// The function must write the computed value in the last argument
|
||||
// (the only non-const one) and return true to indicate
|
||||
// success.
|
||||
//
|
||||
// For example, consider a scalar error e = x'y - a, where both x and y are
|
||||
// two-dimensional column vector parameters, the prime sign indicates
|
||||
// transposition, and a is a constant.
|
||||
//
|
||||
// To write an auto-differentiable FirstOrderFunction for the above model, first
|
||||
// define the object
|
||||
//
|
||||
// class QuadraticCostFunctor {
|
||||
// public:
|
||||
// explicit QuadraticCostFunctor(double a) : a_(a) {}
|
||||
// template <typename T>
|
||||
// bool operator()(const T* const xy, T* cost) const {
|
||||
// const T* const x = xy;
|
||||
// const T* const y = xy + 2;
|
||||
// *cost = x[0] * y[0] + x[1] * y[1] - T(a_);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// double a_;
|
||||
// };
|
||||
//
|
||||
// Note that in the declaration of operator() the input parameters xy come
|
||||
// first, and are passed as const pointers to arrays of T. The
|
||||
// output is the last parameter.
|
||||
//
|
||||
// Then given this class definition, the auto differentiated FirstOrderFunction
|
||||
// for it can be constructed as follows.
|
||||
//
|
||||
// FirstOrderFunction* function =
|
||||
// new AutoDiffFirstOrderFunction<QuadraticCostFunctor, 4>(
|
||||
// new QuadraticCostFunctor(1.0)));
|
||||
//
|
||||
// In the instantiation above, the template parameters following
|
||||
// "QuadraticCostFunctor", "4", describe the functor as computing a
|
||||
// 1-dimensional output from a four dimensional vector.
|
||||
//
|
||||
// WARNING: Since the functor will get instantiated with different types for
|
||||
// T, you must convert from other numeric types to T before mixing
|
||||
// computations with other variables of type T. In the example above, this is
|
||||
// seen where instead of using a_ directly, a_ is wrapped with T(a_).
|
||||
|
||||
template <typename FirstOrderFunctor, int kNumParameters>
|
||||
class AutoDiffFirstOrderFunction : public FirstOrderFunction {
|
||||
public:
|
||||
// Takes ownership of functor.
|
||||
explicit AutoDiffFirstOrderFunction(FirstOrderFunctor* functor)
|
||||
: functor_(functor) {
|
||||
static_assert(kNumParameters > 0, "kNumParameters must be positive");
|
||||
}
|
||||
|
||||
virtual ~AutoDiffFirstOrderFunction() {}
|
||||
|
||||
bool Evaluate(const double* const parameters,
|
||||
double* cost,
|
||||
double* gradient) const override {
|
||||
if (gradient == nullptr) {
|
||||
return (*functor_)(parameters, cost);
|
||||
}
|
||||
|
||||
typedef Jet<double, kNumParameters> JetT;
|
||||
internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(kNumParameters);
|
||||
for (int i = 0; i < kNumParameters; ++i) {
|
||||
x[i].a = parameters[i];
|
||||
x[i].v.setZero();
|
||||
x[i].v[i] = 1.0;
|
||||
}
|
||||
|
||||
JetT output;
|
||||
output.a = kImpossibleValue;
|
||||
output.v.setConstant(kImpossibleValue);
|
||||
|
||||
if (!(*functor_)(x.data(), &output)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*cost = output.a;
|
||||
VectorRef(gradient, kNumParameters) = output.v;
|
||||
return true;
|
||||
}
|
||||
|
||||
int NumParameters() const override { return kNumParameters; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<FirstOrderFunctor> functor_;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_AUTODIFF_FIRST_ORDER_FUNCTION_H_
|
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,9 +33,10 @@
|
||||
#ifndef CERES_PUBLIC_AUTODIFF_LOCAL_PARAMETERIZATION_H_
|
||||
#define CERES_PUBLIC_AUTODIFF_LOCAL_PARAMETERIZATION_H_
|
||||
|
||||
#include "ceres/local_parameterization.h"
|
||||
#include <memory>
|
||||
|
||||
#include "ceres/internal/autodiff.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/local_parameterization.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
@@ -107,21 +108,20 @@ namespace ceres {
|
||||
template <typename Functor, int kGlobalSize, int kLocalSize>
|
||||
class AutoDiffLocalParameterization : public LocalParameterization {
|
||||
public:
|
||||
AutoDiffLocalParameterization() :
|
||||
functor_(new Functor()) {}
|
||||
AutoDiffLocalParameterization() : functor_(new Functor()) {}
|
||||
|
||||
// Takes ownership of functor.
|
||||
explicit AutoDiffLocalParameterization(Functor* functor) :
|
||||
functor_(functor) {}
|
||||
explicit AutoDiffLocalParameterization(Functor* functor)
|
||||
: functor_(functor) {}
|
||||
|
||||
virtual ~AutoDiffLocalParameterization() {}
|
||||
virtual bool Plus(const double* x,
|
||||
const double* delta,
|
||||
double* x_plus_delta) const {
|
||||
bool Plus(const double* x,
|
||||
const double* delta,
|
||||
double* x_plus_delta) const override {
|
||||
return (*functor_)(x, delta, x_plus_delta);
|
||||
}
|
||||
|
||||
virtual bool ComputeJacobian(const double* x, double* jacobian) const {
|
||||
bool ComputeJacobian(const double* x, double* jacobian) const override {
|
||||
double zero_delta[kLocalSize];
|
||||
for (int i = 0; i < kLocalSize; ++i) {
|
||||
zero_delta[i] = 0.0;
|
||||
@@ -133,20 +133,18 @@ class AutoDiffLocalParameterization : public LocalParameterization {
|
||||
}
|
||||
|
||||
const double* parameter_ptrs[2] = {x, zero_delta};
|
||||
double* jacobian_ptrs[2] = { NULL, jacobian };
|
||||
return internal::AutoDiff<Functor, double, kGlobalSize, kLocalSize>
|
||||
::Differentiate(*functor_,
|
||||
parameter_ptrs,
|
||||
kGlobalSize,
|
||||
x_plus_delta,
|
||||
jacobian_ptrs);
|
||||
double* jacobian_ptrs[2] = {NULL, jacobian};
|
||||
return internal::AutoDifferentiate<
|
||||
kGlobalSize,
|
||||
internal::StaticParameterDims<kGlobalSize, kLocalSize>>(
|
||||
*functor_, parameter_ptrs, kGlobalSize, x_plus_delta, jacobian_ptrs);
|
||||
}
|
||||
|
||||
virtual int GlobalSize() const { return kGlobalSize; }
|
||||
virtual int LocalSize() const { return kLocalSize; }
|
||||
int GlobalSize() const override { return kGlobalSize; }
|
||||
int LocalSize() const override { return kLocalSize; }
|
||||
|
||||
private:
|
||||
internal::scoped_ptr<Functor> functor_;
|
||||
std::unique_ptr<Functor> functor_;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
4
extern/ceres/include/ceres/c_api.h
vendored
4
extern/ceres/include/ceres/c_api.h
vendored
@@ -1,5 +1,5 @@
|
||||
/* Ceres Solver - A fast non-linear least squares minimizer
|
||||
* Copyright 2015 Google Inc. All rights reserved.
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
* http://ceres-solver.org/
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -143,4 +143,4 @@ CERES_EXPORT void ceres_solve(ceres_problem_t* problem);
|
||||
|
||||
#include "ceres/internal/reenable_warnings.h"
|
||||
|
||||
#endif /* CERES_PUBLIC_C_API_H_ */
|
||||
#endif /* CERES_PUBLIC_C_API_H_ */
|
||||
|
9
extern/ceres/include/ceres/ceres.h
vendored
9
extern/ceres/include/ceres/ceres.h
vendored
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -36,12 +36,18 @@
|
||||
|
||||
#include "ceres/autodiff_cost_function.h"
|
||||
#include "ceres/autodiff_local_parameterization.h"
|
||||
#include "ceres/conditioned_cost_function.h"
|
||||
#include "ceres/context.h"
|
||||
#include "ceres/cost_function.h"
|
||||
#include "ceres/cost_function_to_functor.h"
|
||||
#include "ceres/covariance.h"
|
||||
#include "ceres/crs_matrix.h"
|
||||
#include "ceres/dynamic_autodiff_cost_function.h"
|
||||
#include "ceres/dynamic_cost_function.h"
|
||||
#include "ceres/dynamic_cost_function_to_functor.h"
|
||||
#include "ceres/dynamic_numeric_diff_cost_function.h"
|
||||
#include "ceres/evaluation_callback.h"
|
||||
#include "ceres/gradient_checker.h"
|
||||
#include "ceres/gradient_problem.h"
|
||||
#include "ceres/gradient_problem_solver.h"
|
||||
#include "ceres/iteration_callback.h"
|
||||
@@ -49,6 +55,7 @@
|
||||
#include "ceres/local_parameterization.h"
|
||||
#include "ceres/loss_function.h"
|
||||
#include "ceres/numeric_diff_cost_function.h"
|
||||
#include "ceres/numeric_diff_options.h"
|
||||
#include "ceres/ordered_groups.h"
|
||||
#include "ceres/problem.h"
|
||||
#include "ceres/sized_cost_function.h"
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,12 +34,12 @@
|
||||
#ifndef CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
|
||||
#define CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/cost_function.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/types.h"
|
||||
#include "ceres/internal/disable_warnings.h"
|
||||
#include "ceres/types.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
@@ -77,17 +77,19 @@ class CERES_EXPORT ConditionedCostFunction : public CostFunction {
|
||||
// per-residual conditioner. Takes ownership of all of the wrapped cost
|
||||
// functions, or not, depending on the ownership parameter. Conditioners
|
||||
// may be NULL, in which case the corresponding residual is not modified.
|
||||
//
|
||||
// The conditioners can repeat.
|
||||
ConditionedCostFunction(CostFunction* wrapped_cost_function,
|
||||
const std::vector<CostFunction*>& conditioners,
|
||||
Ownership ownership);
|
||||
virtual ~ConditionedCostFunction();
|
||||
|
||||
virtual bool Evaluate(double const* const* parameters,
|
||||
double* residuals,
|
||||
double** jacobians) const;
|
||||
bool Evaluate(double const* const* parameters,
|
||||
double* residuals,
|
||||
double** jacobians) const override;
|
||||
|
||||
private:
|
||||
internal::scoped_ptr<CostFunction> wrapped_cost_function_;
|
||||
std::unique_ptr<CostFunction> wrapped_cost_function_;
|
||||
std::vector<CostFunction*> conditioners_;
|
||||
Ownership ownership_;
|
||||
};
|
||||
|
56
extern/ceres/include/ceres/context.h
vendored
Normal file
56
extern/ceres/include/ceres/context.h
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: vitus@google.com (Michael Vitus)
|
||||
|
||||
#ifndef CERES_PUBLIC_CONTEXT_H_
|
||||
#define CERES_PUBLIC_CONTEXT_H_
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// A global context for processing data in Ceres. This provides a mechanism to
|
||||
// allow Ceres to reuse items that are expensive to create between multiple
|
||||
// calls; for example, thread pools. The same Context can be used on multiple
|
||||
// Problems, either serially or in parallel. When using it with multiple
|
||||
// Problems at the same time, they may end up contending for resources
|
||||
// (e.g. threads) managed by the Context.
|
||||
class Context {
|
||||
public:
|
||||
Context() {}
|
||||
Context(const Context&) = delete;
|
||||
void operator=(const Context&) = delete;
|
||||
|
||||
virtual ~Context() {}
|
||||
|
||||
// Creates a context object and the caller takes ownership.
|
||||
static Context* Create();
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_CONTEXT_H_
|
27
extern/ceres/include/ceres/cost_function.h
vendored
27
extern/ceres/include/ceres/cost_function.h
vendored
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -44,18 +44,18 @@
|
||||
#ifndef CERES_PUBLIC_COST_FUNCTION_H_
|
||||
#define CERES_PUBLIC_COST_FUNCTION_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "ceres/internal/macros.h"
|
||||
#include "ceres/internal/port.h"
|
||||
#include "ceres/types.h"
|
||||
|
||||
#include "ceres/internal/disable_warnings.h"
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// This class implements the computation of the cost (a.k.a. residual) terms as
|
||||
// a function of the input (control) variables, and is the interface for users
|
||||
// to describe their least squares problem to Ceres. In other words, this is the
|
||||
// modelling layer between users and the Ceres optimizer. The signature of the
|
||||
// modeling layer between users and the Ceres optimizer. The signature of the
|
||||
// function (number and sizes of input parameter blocks and number of outputs)
|
||||
// is stored in parameter_block_sizes_ and num_residuals_ respectively. User
|
||||
// code inheriting from this class is expected to set these two members with the
|
||||
@@ -64,6 +64,8 @@ namespace ceres {
|
||||
class CERES_EXPORT CostFunction {
|
||||
public:
|
||||
CostFunction() : num_residuals_(0) {}
|
||||
CostFunction(const CostFunction&) = delete;
|
||||
void operator=(const CostFunction&) = delete;
|
||||
|
||||
virtual ~CostFunction() {}
|
||||
|
||||
@@ -115,29 +117,24 @@ class CERES_EXPORT CostFunction {
|
||||
double* residuals,
|
||||
double** jacobians) const = 0;
|
||||
|
||||
const std::vector<int32>& parameter_block_sizes() const {
|
||||
const std::vector<int32_t>& parameter_block_sizes() const {
|
||||
return parameter_block_sizes_;
|
||||
}
|
||||
|
||||
int num_residuals() const {
|
||||
return num_residuals_;
|
||||
}
|
||||
int num_residuals() const { return num_residuals_; }
|
||||
|
||||
protected:
|
||||
std::vector<int32>* mutable_parameter_block_sizes() {
|
||||
std::vector<int32_t>* mutable_parameter_block_sizes() {
|
||||
return ¶meter_block_sizes_;
|
||||
}
|
||||
|
||||
void set_num_residuals(int num_residuals) {
|
||||
num_residuals_ = num_residuals;
|
||||
}
|
||||
void set_num_residuals(int num_residuals) { num_residuals_ = num_residuals; }
|
||||
|
||||
private:
|
||||
// Cost function signature metadata: number of inputs & their sizes,
|
||||
// number of outputs (residuals).
|
||||
std::vector<int32> parameter_block_sizes_;
|
||||
std::vector<int32_t> parameter_block_sizes_;
|
||||
int num_residuals_;
|
||||
CERES_DISALLOW_COPY_AND_ASSIGN(CostFunction);
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,7 +30,7 @@
|
||||
//
|
||||
// CostFunctionToFunctor is an adapter class that allows users to use
|
||||
// SizedCostFunction objects in templated functors which are to be used for
|
||||
// automatic differentiation. This allows the user to seamlessly mix
|
||||
// automatic differentiation. This allows the user to seamlessly mix
|
||||
// analytic, numeric and automatic differentiation.
|
||||
//
|
||||
// For example, let us assume that
|
||||
@@ -38,16 +38,15 @@
|
||||
// class IntrinsicProjection : public SizedCostFunction<2, 5, 3> {
|
||||
// public:
|
||||
// IntrinsicProjection(const double* observation);
|
||||
// virtual bool Evaluate(double const* const* parameters,
|
||||
// double* residuals,
|
||||
// double** jacobians) const;
|
||||
// bool Evaluate(double const* const* parameters,
|
||||
// double* residuals,
|
||||
// double** jacobians) const override;
|
||||
// };
|
||||
//
|
||||
// is a cost function that implements the projection of a point in its
|
||||
// local coordinate system onto its image plane and subtracts it from
|
||||
// the observed point projection. It can compute its residual and
|
||||
// either via analytic or numerical differentiation can compute its
|
||||
// jacobians.
|
||||
// jacobians either via analytic or numerical differentiation.
|
||||
//
|
||||
// Now we would like to compose the action of this CostFunction with
|
||||
// the action of camera extrinsics, i.e., rotation and
|
||||
@@ -87,594 +86,83 @@
|
||||
#ifndef CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
|
||||
#define CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/cost_function.h"
|
||||
#include "ceres/dynamic_cost_function_to_functor.h"
|
||||
#include "ceres/internal/fixed_array.h"
|
||||
#include "ceres/internal/parameter_dims.h"
|
||||
#include "ceres/internal/port.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/types.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
template <int kNumResiduals,
|
||||
int N0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0,
|
||||
int N5 = 0, int N6 = 0, int N7 = 0, int N8 = 0, int N9 = 0>
|
||||
template <int kNumResiduals, int... Ns>
|
||||
class CostFunctionToFunctor {
|
||||
public:
|
||||
// Takes ownership of cost_function.
|
||||
explicit CostFunctionToFunctor(CostFunction* cost_function)
|
||||
: cost_functor_(cost_function) {
|
||||
CHECK_NOTNULL(cost_function);
|
||||
CHECK(cost_function != nullptr);
|
||||
CHECK(kNumResiduals > 0 || kNumResiduals == DYNAMIC);
|
||||
|
||||
// This block breaks the 80 column rule to keep it somewhat readable.
|
||||
CHECK((!N1 && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
|
||||
((N1 > 0) && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
|
||||
((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5 && !N6 && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && !N6 && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && (N9 > 0))) // NOLINT
|
||||
<< "Zero block cannot precede a non-zero block. Block sizes are "
|
||||
<< "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", "
|
||||
<< N3 << ", " << N4 << ", " << N5 << ", " << N6 << ", " << N7 << ", "
|
||||
<< N8 << ", " << N9;
|
||||
|
||||
const std::vector<int32>& parameter_block_sizes =
|
||||
const std::vector<int32_t>& parameter_block_sizes =
|
||||
cost_function->parameter_block_sizes();
|
||||
const int num_parameter_blocks =
|
||||
(N0 > 0) + (N1 > 0) + (N2 > 0) + (N3 > 0) + (N4 > 0) +
|
||||
(N5 > 0) + (N6 > 0) + (N7 > 0) + (N8 > 0) + (N9 > 0);
|
||||
const int num_parameter_blocks = ParameterDims::kNumParameterBlocks;
|
||||
CHECK_EQ(static_cast<int>(parameter_block_sizes.size()),
|
||||
num_parameter_blocks);
|
||||
|
||||
CHECK_EQ(N0, parameter_block_sizes[0]);
|
||||
if (parameter_block_sizes.size() > 1) CHECK_EQ(N1, parameter_block_sizes[1]); // NOLINT
|
||||
if (parameter_block_sizes.size() > 2) CHECK_EQ(N2, parameter_block_sizes[2]); // NOLINT
|
||||
if (parameter_block_sizes.size() > 3) CHECK_EQ(N3, parameter_block_sizes[3]); // NOLINT
|
||||
if (parameter_block_sizes.size() > 4) CHECK_EQ(N4, parameter_block_sizes[4]); // NOLINT
|
||||
if (parameter_block_sizes.size() > 5) CHECK_EQ(N5, parameter_block_sizes[5]); // NOLINT
|
||||
if (parameter_block_sizes.size() > 6) CHECK_EQ(N6, parameter_block_sizes[6]); // NOLINT
|
||||
if (parameter_block_sizes.size() > 7) CHECK_EQ(N7, parameter_block_sizes[7]); // NOLINT
|
||||
if (parameter_block_sizes.size() > 8) CHECK_EQ(N8, parameter_block_sizes[8]); // NOLINT
|
||||
if (parameter_block_sizes.size() > 9) CHECK_EQ(N9, parameter_block_sizes[9]); // NOLINT
|
||||
if (parameter_block_sizes.size() == num_parameter_blocks) {
|
||||
for (int block = 0; block < num_parameter_blocks; ++block) {
|
||||
CHECK_EQ(ParameterDims::GetDim(block), parameter_block_sizes[block])
|
||||
<< "Parameter block size missmatch. The specified static parameter "
|
||||
"block dimension does not match the one from the cost function.";
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_EQ(accumulate(parameter_block_sizes.begin(),
|
||||
parameter_block_sizes.end(), 0),
|
||||
N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9);
|
||||
CHECK_EQ(accumulate(
|
||||
parameter_block_sizes.begin(), parameter_block_sizes.end(), 0),
|
||||
ParameterDims::kNumParameters);
|
||||
}
|
||||
|
||||
bool operator()(const double* x0, double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_EQ(N1, 0);
|
||||
CHECK_EQ(N2, 0);
|
||||
CHECK_EQ(N3, 0);
|
||||
CHECK_EQ(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
template <typename T, typename... Ts>
|
||||
bool operator()(const T* p1, Ts*... ps) const {
|
||||
// Add one because of residual block.
|
||||
static_assert(sizeof...(Ts) + 1 == ParameterDims::kNumParameterBlocks + 1,
|
||||
"Invalid number of parameter blocks specified.");
|
||||
|
||||
return cost_functor_(&x0, residuals);
|
||||
}
|
||||
auto params = std::make_tuple(p1, ps...);
|
||||
|
||||
bool operator()(const double* x0,
|
||||
const double* x1,
|
||||
double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_EQ(N2, 0);
|
||||
CHECK_EQ(N3, 0);
|
||||
CHECK_EQ(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const double*> parameter_blocks(2);
|
||||
parameter_blocks[0] = x0;
|
||||
parameter_blocks[1] = x1;
|
||||
return cost_functor_(parameter_blocks.get(), residuals);
|
||||
}
|
||||
// Extract residual pointer from params. The residual pointer is the
|
||||
// last pointer.
|
||||
constexpr int kResidualIndex = ParameterDims::kNumParameterBlocks;
|
||||
T* residuals = std::get<kResidualIndex>(params);
|
||||
|
||||
bool operator()(const double* x0,
|
||||
const double* x1,
|
||||
const double* x2,
|
||||
double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_EQ(N3, 0);
|
||||
CHECK_EQ(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const double*> parameter_blocks(3);
|
||||
parameter_blocks[0] = x0;
|
||||
parameter_blocks[1] = x1;
|
||||
parameter_blocks[2] = x2;
|
||||
return cost_functor_(parameter_blocks.get(), residuals);
|
||||
}
|
||||
// Extract parameter block pointers from params.
|
||||
using Indices =
|
||||
std::make_integer_sequence<int,
|
||||
ParameterDims::kNumParameterBlocks>;
|
||||
std::array<const T*, ParameterDims::kNumParameterBlocks> parameter_blocks =
|
||||
GetParameterPointers<T>(params, Indices());
|
||||
|
||||
bool operator()(const double* x0,
|
||||
const double* x1,
|
||||
const double* x2,
|
||||
const double* x3,
|
||||
double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_EQ(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const double*> parameter_blocks(4);
|
||||
parameter_blocks[0] = x0;
|
||||
parameter_blocks[1] = x1;
|
||||
parameter_blocks[2] = x2;
|
||||
parameter_blocks[3] = x3;
|
||||
return cost_functor_(parameter_blocks.get(), residuals);
|
||||
}
|
||||
|
||||
bool operator()(const double* x0,
|
||||
const double* x1,
|
||||
const double* x2,
|
||||
const double* x3,
|
||||
const double* x4,
|
||||
double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const double*> parameter_blocks(5);
|
||||
parameter_blocks[0] = x0;
|
||||
parameter_blocks[1] = x1;
|
||||
parameter_blocks[2] = x2;
|
||||
parameter_blocks[3] = x3;
|
||||
parameter_blocks[4] = x4;
|
||||
return cost_functor_(parameter_blocks.get(), residuals);
|
||||
}
|
||||
|
||||
bool operator()(const double* x0,
|
||||
const double* x1,
|
||||
const double* x2,
|
||||
const double* x3,
|
||||
const double* x4,
|
||||
const double* x5,
|
||||
double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const double*> parameter_blocks(6);
|
||||
parameter_blocks[0] = x0;
|
||||
parameter_blocks[1] = x1;
|
||||
parameter_blocks[2] = x2;
|
||||
parameter_blocks[3] = x3;
|
||||
parameter_blocks[4] = x4;
|
||||
parameter_blocks[5] = x5;
|
||||
return cost_functor_(parameter_blocks.get(), residuals);
|
||||
}
|
||||
|
||||
bool operator()(const double* x0,
|
||||
const double* x1,
|
||||
const double* x2,
|
||||
const double* x3,
|
||||
const double* x4,
|
||||
const double* x5,
|
||||
const double* x6,
|
||||
double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_NE(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const double*> parameter_blocks(7);
|
||||
parameter_blocks[0] = x0;
|
||||
parameter_blocks[1] = x1;
|
||||
parameter_blocks[2] = x2;
|
||||
parameter_blocks[3] = x3;
|
||||
parameter_blocks[4] = x4;
|
||||
parameter_blocks[5] = x5;
|
||||
parameter_blocks[6] = x6;
|
||||
return cost_functor_(parameter_blocks.get(), residuals);
|
||||
}
|
||||
|
||||
bool operator()(const double* x0,
|
||||
const double* x1,
|
||||
const double* x2,
|
||||
const double* x3,
|
||||
const double* x4,
|
||||
const double* x5,
|
||||
const double* x6,
|
||||
const double* x7,
|
||||
double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_NE(N6, 0);
|
||||
CHECK_NE(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const double*> parameter_blocks(8);
|
||||
parameter_blocks[0] = x0;
|
||||
parameter_blocks[1] = x1;
|
||||
parameter_blocks[2] = x2;
|
||||
parameter_blocks[3] = x3;
|
||||
parameter_blocks[4] = x4;
|
||||
parameter_blocks[5] = x5;
|
||||
parameter_blocks[6] = x6;
|
||||
parameter_blocks[7] = x7;
|
||||
return cost_functor_(parameter_blocks.get(), residuals);
|
||||
}
|
||||
|
||||
bool operator()(const double* x0,
|
||||
const double* x1,
|
||||
const double* x2,
|
||||
const double* x3,
|
||||
const double* x4,
|
||||
const double* x5,
|
||||
const double* x6,
|
||||
const double* x7,
|
||||
const double* x8,
|
||||
double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_NE(N6, 0);
|
||||
CHECK_NE(N7, 0);
|
||||
CHECK_NE(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const double*> parameter_blocks(9);
|
||||
parameter_blocks[0] = x0;
|
||||
parameter_blocks[1] = x1;
|
||||
parameter_blocks[2] = x2;
|
||||
parameter_blocks[3] = x3;
|
||||
parameter_blocks[4] = x4;
|
||||
parameter_blocks[5] = x5;
|
||||
parameter_blocks[6] = x6;
|
||||
parameter_blocks[7] = x7;
|
||||
parameter_blocks[8] = x8;
|
||||
return cost_functor_(parameter_blocks.get(), residuals);
|
||||
}
|
||||
|
||||
bool operator()(const double* x0,
|
||||
const double* x1,
|
||||
const double* x2,
|
||||
const double* x3,
|
||||
const double* x4,
|
||||
const double* x5,
|
||||
const double* x6,
|
||||
const double* x7,
|
||||
const double* x8,
|
||||
const double* x9,
|
||||
double* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_NE(N6, 0);
|
||||
CHECK_NE(N7, 0);
|
||||
CHECK_NE(N8, 0);
|
||||
CHECK_NE(N9, 0);
|
||||
internal::FixedArray<const double*> parameter_blocks(10);
|
||||
parameter_blocks[0] = x0;
|
||||
parameter_blocks[1] = x1;
|
||||
parameter_blocks[2] = x2;
|
||||
parameter_blocks[3] = x3;
|
||||
parameter_blocks[4] = x4;
|
||||
parameter_blocks[5] = x5;
|
||||
parameter_blocks[6] = x6;
|
||||
parameter_blocks[7] = x7;
|
||||
parameter_blocks[8] = x8;
|
||||
parameter_blocks[9] = x9;
|
||||
return cost_functor_(parameter_blocks.get(), residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0, JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_EQ(N1, 0);
|
||||
CHECK_EQ(N2, 0);
|
||||
CHECK_EQ(N3, 0);
|
||||
CHECK_EQ(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
return cost_functor_(&x0, residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0,
|
||||
const JetT* x1,
|
||||
JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_EQ(N2, 0);
|
||||
CHECK_EQ(N3, 0);
|
||||
CHECK_EQ(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const JetT*> jets(2);
|
||||
jets[0] = x0;
|
||||
jets[1] = x1;
|
||||
return cost_functor_(jets.get(), residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0,
|
||||
const JetT* x1,
|
||||
const JetT* x2,
|
||||
JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_EQ(N3, 0);
|
||||
CHECK_EQ(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const JetT*> jets(3);
|
||||
jets[0] = x0;
|
||||
jets[1] = x1;
|
||||
jets[2] = x2;
|
||||
return cost_functor_(jets.get(), residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0,
|
||||
const JetT* x1,
|
||||
const JetT* x2,
|
||||
const JetT* x3,
|
||||
JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_EQ(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const JetT*> jets(4);
|
||||
jets[0] = x0;
|
||||
jets[1] = x1;
|
||||
jets[2] = x2;
|
||||
jets[3] = x3;
|
||||
return cost_functor_(jets.get(), residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0,
|
||||
const JetT* x1,
|
||||
const JetT* x2,
|
||||
const JetT* x3,
|
||||
const JetT* x4,
|
||||
JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_EQ(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const JetT*> jets(5);
|
||||
jets[0] = x0;
|
||||
jets[1] = x1;
|
||||
jets[2] = x2;
|
||||
jets[3] = x3;
|
||||
jets[4] = x4;
|
||||
return cost_functor_(jets.get(), residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0,
|
||||
const JetT* x1,
|
||||
const JetT* x2,
|
||||
const JetT* x3,
|
||||
const JetT* x4,
|
||||
const JetT* x5,
|
||||
JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_EQ(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const JetT*> jets(6);
|
||||
jets[0] = x0;
|
||||
jets[1] = x1;
|
||||
jets[2] = x2;
|
||||
jets[3] = x3;
|
||||
jets[4] = x4;
|
||||
jets[5] = x5;
|
||||
return cost_functor_(jets.get(), residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0,
|
||||
const JetT* x1,
|
||||
const JetT* x2,
|
||||
const JetT* x3,
|
||||
const JetT* x4,
|
||||
const JetT* x5,
|
||||
const JetT* x6,
|
||||
JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_NE(N6, 0);
|
||||
CHECK_EQ(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const JetT*> jets(7);
|
||||
jets[0] = x0;
|
||||
jets[1] = x1;
|
||||
jets[2] = x2;
|
||||
jets[3] = x3;
|
||||
jets[4] = x4;
|
||||
jets[5] = x5;
|
||||
jets[6] = x6;
|
||||
return cost_functor_(jets.get(), residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0,
|
||||
const JetT* x1,
|
||||
const JetT* x2,
|
||||
const JetT* x3,
|
||||
const JetT* x4,
|
||||
const JetT* x5,
|
||||
const JetT* x6,
|
||||
const JetT* x7,
|
||||
JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_NE(N6, 0);
|
||||
CHECK_NE(N7, 0);
|
||||
CHECK_EQ(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const JetT*> jets(8);
|
||||
jets[0] = x0;
|
||||
jets[1] = x1;
|
||||
jets[2] = x2;
|
||||
jets[3] = x3;
|
||||
jets[4] = x4;
|
||||
jets[5] = x5;
|
||||
jets[6] = x6;
|
||||
jets[7] = x7;
|
||||
return cost_functor_(jets.get(), residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0,
|
||||
const JetT* x1,
|
||||
const JetT* x2,
|
||||
const JetT* x3,
|
||||
const JetT* x4,
|
||||
const JetT* x5,
|
||||
const JetT* x6,
|
||||
const JetT* x7,
|
||||
const JetT* x8,
|
||||
JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_NE(N6, 0);
|
||||
CHECK_NE(N7, 0);
|
||||
CHECK_NE(N8, 0);
|
||||
CHECK_EQ(N9, 0);
|
||||
internal::FixedArray<const JetT*> jets(9);
|
||||
jets[0] = x0;
|
||||
jets[1] = x1;
|
||||
jets[2] = x2;
|
||||
jets[3] = x3;
|
||||
jets[4] = x4;
|
||||
jets[5] = x5;
|
||||
jets[6] = x6;
|
||||
jets[7] = x7;
|
||||
jets[8] = x8;
|
||||
return cost_functor_(jets.get(), residuals);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(const JetT* x0,
|
||||
const JetT* x1,
|
||||
const JetT* x2,
|
||||
const JetT* x3,
|
||||
const JetT* x4,
|
||||
const JetT* x5,
|
||||
const JetT* x6,
|
||||
const JetT* x7,
|
||||
const JetT* x8,
|
||||
const JetT* x9,
|
||||
JetT* residuals) const {
|
||||
CHECK_NE(N0, 0);
|
||||
CHECK_NE(N1, 0);
|
||||
CHECK_NE(N2, 0);
|
||||
CHECK_NE(N3, 0);
|
||||
CHECK_NE(N4, 0);
|
||||
CHECK_NE(N5, 0);
|
||||
CHECK_NE(N6, 0);
|
||||
CHECK_NE(N7, 0);
|
||||
CHECK_NE(N8, 0);
|
||||
CHECK_NE(N9, 0);
|
||||
internal::FixedArray<const JetT*> jets(10);
|
||||
jets[0] = x0;
|
||||
jets[1] = x1;
|
||||
jets[2] = x2;
|
||||
jets[3] = x3;
|
||||
jets[4] = x4;
|
||||
jets[5] = x5;
|
||||
jets[6] = x6;
|
||||
jets[7] = x7;
|
||||
jets[8] = x8;
|
||||
jets[9] = x9;
|
||||
return cost_functor_(jets.get(), residuals);
|
||||
return cost_functor_(parameter_blocks.data(), residuals);
|
||||
}
|
||||
|
||||
private:
|
||||
using ParameterDims = internal::StaticParameterDims<Ns...>;
|
||||
|
||||
template <typename T, typename Tuple, int... Indices>
|
||||
static std::array<const T*, ParameterDims::kNumParameterBlocks>
|
||||
GetParameterPointers(const Tuple& paramPointers,
|
||||
std::integer_sequence<int, Indices...>) {
|
||||
return std::array<const T*, ParameterDims::kNumParameterBlocks>{
|
||||
{std::get<Indices>(paramPointers)...}};
|
||||
}
|
||||
|
||||
DynamicCostFunctionToFunctor cost_functor_;
|
||||
};
|
||||
|
||||
|
81
extern/ceres/include/ceres/covariance.h
vendored
81
extern/ceres/include/ceres/covariance.h
vendored
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,12 +31,13 @@
|
||||
#ifndef CERES_PUBLIC_COVARIANCE_H_
|
||||
#define CERES_PUBLIC_COVARIANCE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "ceres/internal/port.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/types.h"
|
||||
|
||||
#include "ceres/internal/disable_warnings.h"
|
||||
#include "ceres/internal/port.h"
|
||||
#include "ceres/types.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
@@ -60,7 +61,7 @@ class CovarianceImpl;
|
||||
// Background
|
||||
// ==========
|
||||
// One way to assess the quality of the solution returned by a
|
||||
// non-linear least squares solve is to analyze the covariance of the
|
||||
// non-linear least squares solver is to analyze the covariance of the
|
||||
// solution.
|
||||
//
|
||||
// Let us consider the non-linear regression problem
|
||||
@@ -158,7 +159,7 @@ class CovarianceImpl;
|
||||
// Gauge Invariance
|
||||
// ----------------
|
||||
// In structure from motion (3D reconstruction) problems, the
|
||||
// reconstruction is ambiguous upto a similarity transform. This is
|
||||
// reconstruction is ambiguous up to a similarity transform. This is
|
||||
// known as a Gauge Ambiguity. Handling Gauges correctly requires the
|
||||
// use of SVD or custom inversion algorithms. For small problems the
|
||||
// user can use the dense algorithm. For more details see
|
||||
@@ -183,7 +184,7 @@ class CovarianceImpl;
|
||||
// Covariance::Options options;
|
||||
// Covariance covariance(options);
|
||||
//
|
||||
// std::vector<std::pair<const double*, const double*> > covariance_blocks;
|
||||
// std::vector<std::pair<const double*, const double*>> covariance_blocks;
|
||||
// covariance_blocks.push_back(make_pair(x, x));
|
||||
// covariance_blocks.push_back(make_pair(y, y));
|
||||
// covariance_blocks.push_back(make_pair(x, y));
|
||||
@@ -200,19 +201,19 @@ class CovarianceImpl;
|
||||
class CERES_EXPORT Covariance {
|
||||
public:
|
||||
struct CERES_EXPORT Options {
|
||||
Options()
|
||||
#ifndef CERES_NO_SUITESPARSE
|
||||
: algorithm_type(SUITE_SPARSE_QR),
|
||||
// Sparse linear algebra library to use when a sparse matrix
|
||||
// factorization is being used to compute the covariance matrix.
|
||||
//
|
||||
// Currently this only applies to SPARSE_QR.
|
||||
SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type =
|
||||
#if !defined(CERES_NO_SUITESPARSE)
|
||||
SUITE_SPARSE;
|
||||
#else
|
||||
: algorithm_type(EIGEN_SPARSE_QR),
|
||||
// Eigen's QR factorization is always available.
|
||||
EIGEN_SPARSE;
|
||||
#endif
|
||||
min_reciprocal_condition_number(1e-14),
|
||||
null_space_rank(0),
|
||||
num_threads(1),
|
||||
apply_loss_function(true) {
|
||||
}
|
||||
|
||||
// Ceres supports three different algorithms for covariance
|
||||
// Ceres supports two different algorithms for covariance
|
||||
// estimation, which represent different tradeoffs in speed,
|
||||
// accuracy and reliability.
|
||||
//
|
||||
@@ -229,23 +230,20 @@ class CERES_EXPORT Covariance {
|
||||
// for small to moderate sized problems. It can handle
|
||||
// full-rank as well as rank deficient Jacobians.
|
||||
//
|
||||
// 2. EIGEN_SPARSE_QR uses the sparse QR factorization algorithm
|
||||
// in Eigen to compute the decomposition
|
||||
// 2. SPARSE_QR uses the sparse QR factorization algorithm
|
||||
// to compute the decomposition
|
||||
//
|
||||
// Q * R = J
|
||||
//
|
||||
// [J'J]^-1 = [R*R']^-1
|
||||
//
|
||||
// It is a moderately fast algorithm for sparse matrices.
|
||||
//
|
||||
// 3. SUITE_SPARSE_QR uses the SuiteSparseQR sparse QR
|
||||
// factorization algorithm. It uses dense linear algebra and is
|
||||
// multi threaded, so for large sparse sparse matrices it is
|
||||
// significantly faster than EIGEN_SPARSE_QR.
|
||||
//
|
||||
// Neither EIGEN_SPARSE_QR not SUITE_SPARSE_QR are capable of
|
||||
// computing the covariance if the Jacobian is rank deficient.
|
||||
CovarianceAlgorithmType algorithm_type;
|
||||
// SPARSE_QR is not capable of computing the covariance if the
|
||||
// Jacobian is rank deficient. Depending on the value of
|
||||
// Covariance::Options::sparse_linear_algebra_library_type, either
|
||||
// Eigen's Sparse QR factorization algorithm will be used or
|
||||
// SuiteSparse's high performance SuiteSparseQR algorithm will be
|
||||
// used.
|
||||
CovarianceAlgorithmType algorithm_type = SPARSE_QR;
|
||||
|
||||
// If the Jacobian matrix is near singular, then inverting J'J
|
||||
// will result in unreliable results, e.g, if
|
||||
@@ -270,7 +268,7 @@ class CERES_EXPORT Covariance {
|
||||
// where min_sigma and max_sigma are the minimum and maxiumum
|
||||
// singular values of J respectively.
|
||||
//
|
||||
// 2. SUITE_SPARSE_QR and EIGEN_SPARSE_QR
|
||||
// 2. SPARSE_QR
|
||||
//
|
||||
// rank(J) < num_col(J)
|
||||
//
|
||||
@@ -278,7 +276,7 @@ class CERES_EXPORT Covariance {
|
||||
// sparse QR factorization algorithm. It is a fairly reliable
|
||||
// indication of rank deficiency.
|
||||
//
|
||||
double min_reciprocal_condition_number;
|
||||
double min_reciprocal_condition_number = 1e-14;
|
||||
|
||||
// When using DENSE_SVD, the user has more control in dealing with
|
||||
// singular and near singular covariance matrices.
|
||||
@@ -313,9 +311,9 @@ class CERES_EXPORT Covariance {
|
||||
//
|
||||
// This option has no effect on the SUITE_SPARSE_QR and
|
||||
// EIGEN_SPARSE_QR algorithms.
|
||||
int null_space_rank;
|
||||
int null_space_rank = 0;
|
||||
|
||||
int num_threads;
|
||||
int num_threads = 1;
|
||||
|
||||
// Even though the residual blocks in the problem may contain loss
|
||||
// functions, setting apply_loss_function to false will turn off
|
||||
@@ -323,7 +321,7 @@ class CERES_EXPORT Covariance {
|
||||
// function and in turn its effect on the covariance.
|
||||
//
|
||||
// TODO(sameergaarwal): Expand this based on Jim's experiments.
|
||||
bool apply_loss_function;
|
||||
bool apply_loss_function = true;
|
||||
};
|
||||
|
||||
explicit Covariance(const Options& options);
|
||||
@@ -352,10 +350,9 @@ class CERES_EXPORT Covariance {
|
||||
// covariance computation. Please see the documentation for
|
||||
// Covariance::Options for more on the conditions under which this
|
||||
// function returns false.
|
||||
bool Compute(
|
||||
const std::vector<std::pair<const double*,
|
||||
const double*> >& covariance_blocks,
|
||||
Problem* problem);
|
||||
bool Compute(const std::vector<std::pair<const double*, const double*>>&
|
||||
covariance_blocks,
|
||||
Problem* problem);
|
||||
|
||||
// Compute a part of the covariance matrix.
|
||||
//
|
||||
@@ -428,8 +425,8 @@ class CERES_EXPORT Covariance {
|
||||
// a square matrix whose row and column count is equal to the sum of
|
||||
// the sizes of the individual parameter blocks. The covariance
|
||||
// matrix will be a row-major matrix.
|
||||
bool GetCovarianceMatrix(const std::vector<const double *> ¶meter_blocks,
|
||||
double *covariance_matrix);
|
||||
bool GetCovarianceMatrix(const std::vector<const double*>& parameter_blocks,
|
||||
double* covariance_matrix) const;
|
||||
|
||||
// Return the covariance matrix corresponding to parameter_blocks
|
||||
// in the tangent space if a local parameterization is associated
|
||||
@@ -448,10 +445,10 @@ class CERES_EXPORT Covariance {
|
||||
// blocks. The covariance matrix will be a row-major matrix.
|
||||
bool GetCovarianceMatrixInTangentSpace(
|
||||
const std::vector<const double*>& parameter_blocks,
|
||||
double* covariance_matrix);
|
||||
double* covariance_matrix) const;
|
||||
|
||||
private:
|
||||
internal::scoped_ptr<internal::CovarianceImpl> impl_;
|
||||
std::unique_ptr<internal::CovarianceImpl> impl_;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
5
extern/ceres/include/ceres/crs_matrix.h
vendored
5
extern/ceres/include/ceres/crs_matrix.h
vendored
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,8 +32,9 @@
|
||||
#define CERES_PUBLIC_CRS_MATRIX_H_
|
||||
|
||||
#include <vector>
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
#include "ceres/internal/disable_warnings.h"
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
|
436
extern/ceres/include/ceres/cubic_interpolation.h
vendored
Normal file
436
extern/ceres/include/ceres/cubic_interpolation.h
vendored
Normal file
@@ -0,0 +1,436 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
||||
|
||||
#ifndef CERES_PUBLIC_CUBIC_INTERPOLATION_H_
|
||||
#define CERES_PUBLIC_CUBIC_INTERPOLATION_H_
|
||||
|
||||
#include "Eigen/Core"
|
||||
#include "ceres/internal/port.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// Given samples from a function sampled at four equally spaced points,
|
||||
//
|
||||
// p0 = f(-1)
|
||||
// p1 = f(0)
|
||||
// p2 = f(1)
|
||||
// p3 = f(2)
|
||||
//
|
||||
// Evaluate the cubic Hermite spline (also known as the Catmull-Rom
|
||||
// spline) at a point x that lies in the interval [0, 1].
|
||||
//
|
||||
// This is also the interpolation kernel (for the case of a = 0.5) as
|
||||
// proposed by R. Keys, in:
|
||||
//
|
||||
// "Cubic convolution interpolation for digital image processing".
|
||||
// IEEE Transactions on Acoustics, Speech, and Signal Processing
|
||||
// 29 (6): 1153-1160.
|
||||
//
|
||||
// For more details see
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Cubic_Hermite_spline
|
||||
// http://en.wikipedia.org/wiki/Bicubic_interpolation
|
||||
//
|
||||
// f if not NULL will contain the interpolated function values.
|
||||
// dfdx if not NULL will contain the interpolated derivative values.
|
||||
template <int kDataDimension>
|
||||
void CubicHermiteSpline(const Eigen::Matrix<double, kDataDimension, 1>& p0,
|
||||
const Eigen::Matrix<double, kDataDimension, 1>& p1,
|
||||
const Eigen::Matrix<double, kDataDimension, 1>& p2,
|
||||
const Eigen::Matrix<double, kDataDimension, 1>& p3,
|
||||
const double x,
|
||||
double* f,
|
||||
double* dfdx) {
|
||||
typedef Eigen::Matrix<double, kDataDimension, 1> VType;
|
||||
const VType a = 0.5 * (-p0 + 3.0 * p1 - 3.0 * p2 + p3);
|
||||
const VType b = 0.5 * (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3);
|
||||
const VType c = 0.5 * (-p0 + p2);
|
||||
const VType d = p1;
|
||||
|
||||
// Use Horner's rule to evaluate the function value and its
|
||||
// derivative.
|
||||
|
||||
// f = ax^3 + bx^2 + cx + d
|
||||
if (f != NULL) {
|
||||
Eigen::Map<VType>(f, kDataDimension) = d + x * (c + x * (b + x * a));
|
||||
}
|
||||
|
||||
// dfdx = 3ax^2 + 2bx + c
|
||||
if (dfdx != NULL) {
|
||||
Eigen::Map<VType>(dfdx, kDataDimension) = c + x * (2.0 * b + 3.0 * a * x);
|
||||
}
|
||||
}
|
||||
|
||||
// Given as input an infinite one dimensional grid, which provides the
|
||||
// following interface.
|
||||
//
|
||||
// class Grid {
|
||||
// public:
|
||||
// enum { DATA_DIMENSION = 2; };
|
||||
// void GetValue(int n, double* f) const;
|
||||
// };
|
||||
//
|
||||
// Here, GetValue gives the value of a function f (possibly vector
|
||||
// valued) for any integer n.
|
||||
//
|
||||
// The enum DATA_DIMENSION indicates the dimensionality of the
|
||||
// function being interpolated. For example if you are interpolating
|
||||
// rotations in axis-angle format over time, then DATA_DIMENSION = 3.
|
||||
//
|
||||
// CubicInterpolator uses cubic Hermite splines to produce a smooth
|
||||
// approximation to it that can be used to evaluate the f(x) and f'(x)
|
||||
// at any point on the real number line.
|
||||
//
|
||||
// For more details on cubic interpolation see
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Cubic_Hermite_spline
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// const double data[] = {1.0, 2.0, 5.0, 6.0};
|
||||
// Grid1D<double, 1> grid(data, 0, 4);
|
||||
// CubicInterpolator<Grid1D<double, 1>> interpolator(grid);
|
||||
// double f, dfdx;
|
||||
// interpolator.Evaluator(1.5, &f, &dfdx);
|
||||
template <typename Grid>
|
||||
class CubicInterpolator {
|
||||
public:
|
||||
explicit CubicInterpolator(const Grid& grid) : grid_(grid) {
|
||||
// The + casts the enum into an int before doing the
|
||||
// comparison. It is needed to prevent
|
||||
// "-Wunnamed-type-template-args" related errors.
|
||||
CHECK_GE(+Grid::DATA_DIMENSION, 1);
|
||||
}
|
||||
|
||||
void Evaluate(double x, double* f, double* dfdx) const {
|
||||
const int n = std::floor(x);
|
||||
Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> p0, p1, p2, p3;
|
||||
grid_.GetValue(n - 1, p0.data());
|
||||
grid_.GetValue(n, p1.data());
|
||||
grid_.GetValue(n + 1, p2.data());
|
||||
grid_.GetValue(n + 2, p3.data());
|
||||
CubicHermiteSpline<Grid::DATA_DIMENSION>(p0, p1, p2, p3, x - n, f, dfdx);
|
||||
}
|
||||
|
||||
// The following two Evaluate overloads are needed for interfacing
|
||||
// with automatic differentiation. The first is for when a scalar
|
||||
// evaluation is done, and the second one is for when Jets are used.
|
||||
void Evaluate(const double& x, double* f) const { Evaluate(x, f, NULL); }
|
||||
|
||||
template <typename JetT>
|
||||
void Evaluate(const JetT& x, JetT* f) const {
|
||||
double fx[Grid::DATA_DIMENSION], dfdx[Grid::DATA_DIMENSION];
|
||||
Evaluate(x.a, fx, dfdx);
|
||||
for (int i = 0; i < Grid::DATA_DIMENSION; ++i) {
|
||||
f[i].a = fx[i];
|
||||
f[i].v = dfdx[i] * x.v;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const Grid& grid_;
|
||||
};
|
||||
|
||||
// An object that implements an infinite one dimensional grid needed
|
||||
// by the CubicInterpolator where the source of the function values is
|
||||
// an array of type T on the interval
|
||||
//
|
||||
// [begin, ..., end - 1]
|
||||
//
|
||||
// Since the input array is finite and the grid is infinite, values
|
||||
// outside this interval needs to be computed. Grid1D uses the value
|
||||
// from the nearest edge.
|
||||
//
|
||||
// The function being provided can be vector valued, in which case
|
||||
// kDataDimension > 1. The dimensional slices of the function maybe
|
||||
// interleaved, or they maybe stacked, i.e, if the function has
|
||||
// kDataDimension = 2, if kInterleaved = true, then it is stored as
|
||||
//
|
||||
// f01, f02, f11, f12 ....
|
||||
//
|
||||
// and if kInterleaved = false, then it is stored as
|
||||
//
|
||||
// f01, f11, .. fn1, f02, f12, .. , fn2
|
||||
//
|
||||
template <typename T, int kDataDimension = 1, bool kInterleaved = true>
|
||||
struct Grid1D {
|
||||
public:
|
||||
enum { DATA_DIMENSION = kDataDimension };
|
||||
|
||||
Grid1D(const T* data, const int begin, const int end)
|
||||
: data_(data), begin_(begin), end_(end), num_values_(end - begin) {
|
||||
CHECK_LT(begin, end);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE void GetValue(const int n, double* f) const {
|
||||
const int idx = std::min(std::max(begin_, n), end_ - 1) - begin_;
|
||||
if (kInterleaved) {
|
||||
for (int i = 0; i < kDataDimension; ++i) {
|
||||
f[i] = static_cast<double>(data_[kDataDimension * idx + i]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < kDataDimension; ++i) {
|
||||
f[i] = static_cast<double>(data_[i * num_values_ + idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const T* data_;
|
||||
const int begin_;
|
||||
const int end_;
|
||||
const int num_values_;
|
||||
};
|
||||
|
||||
// Given as input an infinite two dimensional grid like object, which
|
||||
// provides the following interface:
|
||||
//
|
||||
// struct Grid {
|
||||
// enum { DATA_DIMENSION = 1 };
|
||||
// void GetValue(int row, int col, double* f) const;
|
||||
// };
|
||||
//
|
||||
// Where, GetValue gives us the value of a function f (possibly vector
|
||||
// valued) for any pairs of integers (row, col), and the enum
|
||||
// DATA_DIMENSION indicates the dimensionality of the function being
|
||||
// interpolated. For example if you are interpolating a color image
|
||||
// with three channels (Red, Green & Blue), then DATA_DIMENSION = 3.
|
||||
//
|
||||
// BiCubicInterpolator uses the cubic convolution interpolation
|
||||
// algorithm of R. Keys, to produce a smooth approximation to it that
|
||||
// can be used to evaluate the f(r,c), df(r, c)/dr and df(r,c)/dc at
|
||||
// any point in the real plane.
|
||||
//
|
||||
// For more details on the algorithm used here see:
|
||||
//
|
||||
// "Cubic convolution interpolation for digital image processing".
|
||||
// Robert G. Keys, IEEE Trans. on Acoustics, Speech, and Signal
|
||||
// Processing 29 (6): 1153-1160, 1981.
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Cubic_Hermite_spline
|
||||
// http://en.wikipedia.org/wiki/Bicubic_interpolation
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// const double data[] = {1.0, 3.0, -1.0, 4.0,
|
||||
// 3.6, 2.1, 4.2, 2.0,
|
||||
// 2.0, 1.0, 3.1, 5.2};
|
||||
// Grid2D<double, 1> grid(data, 3, 4);
|
||||
// BiCubicInterpolator<Grid2D<double, 1>> interpolator(grid);
|
||||
// double f, dfdr, dfdc;
|
||||
// interpolator.Evaluate(1.2, 2.5, &f, &dfdr, &dfdc);
|
||||
|
||||
template <typename Grid>
|
||||
class BiCubicInterpolator {
|
||||
public:
|
||||
explicit BiCubicInterpolator(const Grid& grid) : grid_(grid) {
|
||||
// The + casts the enum into an int before doing the
|
||||
// comparison. It is needed to prevent
|
||||
// "-Wunnamed-type-template-args" related errors.
|
||||
CHECK_GE(+Grid::DATA_DIMENSION, 1);
|
||||
}
|
||||
|
||||
// Evaluate the interpolated function value and/or its
|
||||
// derivative. Uses the nearest point on the grid boundary if r or
|
||||
// c is out of bounds.
|
||||
void Evaluate(
|
||||
double r, double c, double* f, double* dfdr, double* dfdc) const {
|
||||
// BiCubic interpolation requires 16 values around the point being
|
||||
// evaluated. We will use pij, to indicate the elements of the
|
||||
// 4x4 grid of values.
|
||||
//
|
||||
// col
|
||||
// p00 p01 p02 p03
|
||||
// row p10 p11 p12 p13
|
||||
// p20 p21 p22 p23
|
||||
// p30 p31 p32 p33
|
||||
//
|
||||
// The point (r,c) being evaluated is assumed to lie in the square
|
||||
// defined by p11, p12, p22 and p21.
|
||||
|
||||
const int row = std::floor(r);
|
||||
const int col = std::floor(c);
|
||||
|
||||
Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> p0, p1, p2, p3;
|
||||
|
||||
// Interpolate along each of the four rows, evaluating the function
|
||||
// value and the horizontal derivative in each row.
|
||||
Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> f0, f1, f2, f3;
|
||||
Eigen::Matrix<double, Grid::DATA_DIMENSION, 1> df0dc, df1dc, df2dc, df3dc;
|
||||
|
||||
grid_.GetValue(row - 1, col - 1, p0.data());
|
||||
grid_.GetValue(row - 1, col, p1.data());
|
||||
grid_.GetValue(row - 1, col + 1, p2.data());
|
||||
grid_.GetValue(row - 1, col + 2, p3.data());
|
||||
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
||||
p0, p1, p2, p3, c - col, f0.data(), df0dc.data());
|
||||
|
||||
grid_.GetValue(row, col - 1, p0.data());
|
||||
grid_.GetValue(row, col, p1.data());
|
||||
grid_.GetValue(row, col + 1, p2.data());
|
||||
grid_.GetValue(row, col + 2, p3.data());
|
||||
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
||||
p0, p1, p2, p3, c - col, f1.data(), df1dc.data());
|
||||
|
||||
grid_.GetValue(row + 1, col - 1, p0.data());
|
||||
grid_.GetValue(row + 1, col, p1.data());
|
||||
grid_.GetValue(row + 1, col + 1, p2.data());
|
||||
grid_.GetValue(row + 1, col + 2, p3.data());
|
||||
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
||||
p0, p1, p2, p3, c - col, f2.data(), df2dc.data());
|
||||
|
||||
grid_.GetValue(row + 2, col - 1, p0.data());
|
||||
grid_.GetValue(row + 2, col, p1.data());
|
||||
grid_.GetValue(row + 2, col + 1, p2.data());
|
||||
grid_.GetValue(row + 2, col + 2, p3.data());
|
||||
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
||||
p0, p1, p2, p3, c - col, f3.data(), df3dc.data());
|
||||
|
||||
// Interpolate vertically the interpolated value from each row and
|
||||
// compute the derivative along the columns.
|
||||
CubicHermiteSpline<Grid::DATA_DIMENSION>(f0, f1, f2, f3, r - row, f, dfdr);
|
||||
if (dfdc != NULL) {
|
||||
// Interpolate vertically the derivative along the columns.
|
||||
CubicHermiteSpline<Grid::DATA_DIMENSION>(
|
||||
df0dc, df1dc, df2dc, df3dc, r - row, dfdc, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// The following two Evaluate overloads are needed for interfacing
|
||||
// with automatic differentiation. The first is for when a scalar
|
||||
// evaluation is done, and the second one is for when Jets are used.
|
||||
void Evaluate(const double& r, const double& c, double* f) const {
|
||||
Evaluate(r, c, f, NULL, NULL);
|
||||
}
|
||||
|
||||
template <typename JetT>
|
||||
void Evaluate(const JetT& r, const JetT& c, JetT* f) const {
|
||||
double frc[Grid::DATA_DIMENSION];
|
||||
double dfdr[Grid::DATA_DIMENSION];
|
||||
double dfdc[Grid::DATA_DIMENSION];
|
||||
Evaluate(r.a, c.a, frc, dfdr, dfdc);
|
||||
for (int i = 0; i < Grid::DATA_DIMENSION; ++i) {
|
||||
f[i].a = frc[i];
|
||||
f[i].v = dfdr[i] * r.v + dfdc[i] * c.v;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const Grid& grid_;
|
||||
};
|
||||
|
||||
// An object that implements an infinite two dimensional grid needed
|
||||
// by the BiCubicInterpolator where the source of the function values
|
||||
// is an grid of type T on the grid
|
||||
//
|
||||
// [(row_start, col_start), ..., (row_start, col_end - 1)]
|
||||
// [ ... ]
|
||||
// [(row_end - 1, col_start), ..., (row_end - 1, col_end - 1)]
|
||||
//
|
||||
// Since the input grid is finite and the grid is infinite, values
|
||||
// outside this interval needs to be computed. Grid2D uses the value
|
||||
// from the nearest edge.
|
||||
//
|
||||
// The function being provided can be vector valued, in which case
|
||||
// kDataDimension > 1. The data maybe stored in row or column major
|
||||
// format and the various dimensional slices of the function maybe
|
||||
// interleaved, or they maybe stacked, i.e, if the function has
|
||||
// kDataDimension = 2, is stored in row-major format and if
|
||||
// kInterleaved = true, then it is stored as
|
||||
//
|
||||
// f001, f002, f011, f012, ...
|
||||
//
|
||||
// A commonly occuring example are color images (RGB) where the three
|
||||
// channels are stored interleaved.
|
||||
//
|
||||
// If kInterleaved = false, then it is stored as
|
||||
//
|
||||
// f001, f011, ..., fnm1, f002, f012, ...
|
||||
template <typename T,
|
||||
int kDataDimension = 1,
|
||||
bool kRowMajor = true,
|
||||
bool kInterleaved = true>
|
||||
struct Grid2D {
|
||||
public:
|
||||
enum { DATA_DIMENSION = kDataDimension };
|
||||
|
||||
Grid2D(const T* data,
|
||||
const int row_begin,
|
||||
const int row_end,
|
||||
const int col_begin,
|
||||
const int col_end)
|
||||
: data_(data),
|
||||
row_begin_(row_begin),
|
||||
row_end_(row_end),
|
||||
col_begin_(col_begin),
|
||||
col_end_(col_end),
|
||||
num_rows_(row_end - row_begin),
|
||||
num_cols_(col_end - col_begin),
|
||||
num_values_(num_rows_ * num_cols_) {
|
||||
CHECK_GE(kDataDimension, 1);
|
||||
CHECK_LT(row_begin, row_end);
|
||||
CHECK_LT(col_begin, col_end);
|
||||
}
|
||||
|
||||
EIGEN_STRONG_INLINE void GetValue(const int r, const int c, double* f) const {
|
||||
const int row_idx =
|
||||
std::min(std::max(row_begin_, r), row_end_ - 1) - row_begin_;
|
||||
const int col_idx =
|
||||
std::min(std::max(col_begin_, c), col_end_ - 1) - col_begin_;
|
||||
|
||||
const int n = (kRowMajor) ? num_cols_ * row_idx + col_idx
|
||||
: num_rows_ * col_idx + row_idx;
|
||||
|
||||
if (kInterleaved) {
|
||||
for (int i = 0; i < kDataDimension; ++i) {
|
||||
f[i] = static_cast<double>(data_[kDataDimension * n + i]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < kDataDimension; ++i) {
|
||||
f[i] = static_cast<double>(data_[i * num_values_ + n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const T* data_;
|
||||
const int row_begin_;
|
||||
const int row_end_;
|
||||
const int col_begin_;
|
||||
const int col_end_;
|
||||
const int num_rows_;
|
||||
const int num_cols_;
|
||||
const int num_values_;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_CUBIC_INTERPOLATOR_H_
|
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,7 +28,22 @@
|
||||
//
|
||||
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
||||
// mierle@gmail.com (Keir Mierle)
|
||||
//
|
||||
|
||||
#ifndef CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
|
||||
#define CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/dynamic_cost_function.h"
|
||||
#include "ceres/internal/fixed_array.h"
|
||||
#include "ceres/jet.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// This autodiff implementation differs from the one found in
|
||||
// autodiff_cost_function.h by supporting autodiff on cost functions
|
||||
// with variable numbers of parameters with variable sizes. With the
|
||||
@@ -43,7 +58,7 @@
|
||||
// bool operator()(T const* const* parameters, T* residuals) const {
|
||||
// // Use parameters[i] to access the i'th parameter block.
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// Since the sizing of the parameters is done at runtime, you must
|
||||
// also specify the sizes after creating the dynamic autodiff cost
|
||||
@@ -60,40 +75,17 @@
|
||||
// default, controlled by the Stride template parameter) with each
|
||||
// pass. There is a tradeoff with the size of the passes; you may want
|
||||
// to experiment with the stride.
|
||||
|
||||
#ifndef CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
|
||||
#define CERES_PUBLIC_DYNAMIC_AUTODIFF_COST_FUNCTION_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/cost_function.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/jet.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
template <typename CostFunctor, int Stride = 4>
|
||||
class DynamicAutoDiffCostFunction : public CostFunction {
|
||||
class DynamicAutoDiffCostFunction : public DynamicCostFunction {
|
||||
public:
|
||||
explicit DynamicAutoDiffCostFunction(CostFunctor* functor)
|
||||
: functor_(functor) {}
|
||||
: functor_(functor) {}
|
||||
|
||||
virtual ~DynamicAutoDiffCostFunction() {}
|
||||
|
||||
void AddParameterBlock(int size) {
|
||||
mutable_parameter_block_sizes()->push_back(size);
|
||||
}
|
||||
|
||||
void SetNumResiduals(int num_residuals) {
|
||||
set_num_residuals(num_residuals);
|
||||
}
|
||||
|
||||
virtual bool Evaluate(double const* const* parameters,
|
||||
double* residuals,
|
||||
double** jacobians) const {
|
||||
bool Evaluate(double const* const* parameters,
|
||||
double* residuals,
|
||||
double** jacobians) const override {
|
||||
CHECK_GT(num_residuals(), 0)
|
||||
<< "You must call DynamicAutoDiffCostFunction::SetNumResiduals() "
|
||||
<< "before DynamicAutoDiffCostFunction::Evaluate().";
|
||||
@@ -112,20 +104,23 @@ class DynamicAutoDiffCostFunction : public CostFunction {
|
||||
// depends on.
|
||||
//
|
||||
// To work around this issue, the solution here is to evaluate the
|
||||
// jacobians in a series of passes, each one computing Stripe *
|
||||
// jacobians in a series of passes, each one computing Stride *
|
||||
// num_residuals() derivatives. This is done with small, fixed-size jets.
|
||||
const int num_parameter_blocks = parameter_block_sizes().size();
|
||||
const int num_parameters = std::accumulate(parameter_block_sizes().begin(),
|
||||
parameter_block_sizes().end(),
|
||||
0);
|
||||
const int num_parameter_blocks =
|
||||
static_cast<int>(parameter_block_sizes().size());
|
||||
const int num_parameters = std::accumulate(
|
||||
parameter_block_sizes().begin(), parameter_block_sizes().end(), 0);
|
||||
|
||||
// Allocate scratch space for the strided evaluation.
|
||||
std::vector<Jet<double, Stride> > input_jets(num_parameters);
|
||||
std::vector<Jet<double, Stride> > output_jets(num_residuals());
|
||||
using JetT = Jet<double, Stride>;
|
||||
internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> input_jets(
|
||||
num_parameters);
|
||||
internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> output_jets(
|
||||
num_residuals());
|
||||
|
||||
// Make the parameter pack that is sent to the functor (reused).
|
||||
std::vector<Jet<double, Stride>* > jet_parameters(num_parameter_blocks,
|
||||
static_cast<Jet<double, Stride>* >(NULL));
|
||||
internal::FixedArray<Jet<double, Stride>*> jet_parameters(
|
||||
num_parameter_blocks, nullptr);
|
||||
int num_active_parameters = 0;
|
||||
|
||||
// To handle constant parameters between non-constant parameter blocks, the
|
||||
@@ -172,8 +167,8 @@ class DynamicAutoDiffCostFunction : public CostFunction {
|
||||
// Evaluate all of the strides. Each stride is a chunk of the derivative to
|
||||
// evaluate, typically some size proportional to the size of the SIMD
|
||||
// registers of the CPU.
|
||||
int num_strides = static_cast<int>(ceil(num_active_parameters /
|
||||
static_cast<float>(Stride)));
|
||||
int num_strides = static_cast<int>(
|
||||
ceil(num_active_parameters / static_cast<float>(Stride)));
|
||||
|
||||
int current_derivative_section = 0;
|
||||
int current_derivative_section_cursor = 0;
|
||||
@@ -183,7 +178,7 @@ class DynamicAutoDiffCostFunction : public CostFunction {
|
||||
// non-constant #Stride parameters.
|
||||
const int initial_derivative_section = current_derivative_section;
|
||||
const int initial_derivative_section_cursor =
|
||||
current_derivative_section_cursor;
|
||||
current_derivative_section_cursor;
|
||||
|
||||
int active_parameter_count = 0;
|
||||
parameter_cursor = 0;
|
||||
@@ -193,9 +188,9 @@ class DynamicAutoDiffCostFunction : public CostFunction {
|
||||
++j, parameter_cursor++) {
|
||||
input_jets[parameter_cursor].v.setZero();
|
||||
if (active_parameter_count < Stride &&
|
||||
parameter_cursor >= (
|
||||
start_derivative_section[current_derivative_section] +
|
||||
current_derivative_section_cursor)) {
|
||||
parameter_cursor >=
|
||||
(start_derivative_section[current_derivative_section] +
|
||||
current_derivative_section_cursor)) {
|
||||
if (jacobians[i] != NULL) {
|
||||
input_jets[parameter_cursor].v[active_parameter_count] = 1.0;
|
||||
++active_parameter_count;
|
||||
@@ -222,9 +217,9 @@ class DynamicAutoDiffCostFunction : public CostFunction {
|
||||
for (int j = 0; j < parameter_block_sizes()[i];
|
||||
++j, parameter_cursor++) {
|
||||
if (active_parameter_count < Stride &&
|
||||
parameter_cursor >= (
|
||||
start_derivative_section[current_derivative_section] +
|
||||
current_derivative_section_cursor)) {
|
||||
parameter_cursor >=
|
||||
(start_derivative_section[current_derivative_section] +
|
||||
current_derivative_section_cursor)) {
|
||||
if (jacobians[i] != NULL) {
|
||||
for (int k = 0; k < num_residuals(); ++k) {
|
||||
jacobians[i][k * parameter_block_sizes()[i] + j] =
|
||||
@@ -252,7 +247,7 @@ class DynamicAutoDiffCostFunction : public CostFunction {
|
||||
}
|
||||
|
||||
private:
|
||||
internal::scoped_ptr<CostFunctor> functor_;
|
||||
std::unique_ptr<CostFunctor> functor_;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
56
extern/ceres/include/ceres/dynamic_cost_function.h
vendored
Normal file
56
extern/ceres/include/ceres/dynamic_cost_function.h
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
||||
|
||||
#ifndef CERES_PUBLIC_DYNAMIC_COST_FUNCTION_H_
|
||||
#define CERES_PUBLIC_DYNAMIC_COST_FUNCTION_H_
|
||||
|
||||
#include "ceres/cost_function.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// A common base class for DynamicAutoDiffCostFunction and
|
||||
// DynamicNumericDiffCostFunction which depend on methods that can add
|
||||
// parameter blocks and set the number of residuals at run time.
|
||||
class CERES_EXPORT DynamicCostFunction : public CostFunction {
|
||||
public:
|
||||
~DynamicCostFunction() {}
|
||||
|
||||
virtual void AddParameterBlock(int size) {
|
||||
mutable_parameter_block_sizes()->push_back(size);
|
||||
}
|
||||
|
||||
virtual void SetNumResiduals(int num_residuals) {
|
||||
set_num_residuals(num_residuals);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_DYNAMIC_COST_FUNCTION_H_
|
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,7 +28,20 @@
|
||||
//
|
||||
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
||||
// dgossow@google.com (David Gossow)
|
||||
//
|
||||
|
||||
#ifndef CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
|
||||
#define CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
|
||||
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/dynamic_cost_function.h"
|
||||
#include "ceres/internal/fixed_array.h"
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// DynamicCostFunctionToFunctor allows users to use CostFunction
|
||||
// objects in templated functors which are to be used for automatic
|
||||
// differentiation. It works similar to CostFunctionToFunctor, with the
|
||||
@@ -40,9 +53,9 @@
|
||||
// class IntrinsicProjection : public CostFunction {
|
||||
// public:
|
||||
// IntrinsicProjection(const double* observation);
|
||||
// virtual bool Evaluate(double const* const* parameters,
|
||||
// double* residuals,
|
||||
// double** jacobians) const;
|
||||
// bool Evaluate(double const* const* parameters,
|
||||
// double* residuals,
|
||||
// double** jacobians) const override;
|
||||
// };
|
||||
//
|
||||
// is a cost function that implements the projection of a point in its
|
||||
@@ -87,26 +100,12 @@
|
||||
// private:
|
||||
// DynamicCostFunctionToFunctor intrinsic_projection_;
|
||||
// };
|
||||
|
||||
#ifndef CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
|
||||
#define CERES_PUBLIC_DYNAMIC_COST_FUNCTION_TO_FUNCTOR_H_
|
||||
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/cost_function.h"
|
||||
#include "ceres/internal/fixed_array.h"
|
||||
#include "ceres/internal/port.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
class DynamicCostFunctionToFunctor {
|
||||
public:
|
||||
// Takes ownership of cost_function.
|
||||
explicit DynamicCostFunctionToFunctor(CostFunction* cost_function)
|
||||
: cost_function_(cost_function) {
|
||||
CHECK_NOTNULL(cost_function);
|
||||
CHECK(cost_function != nullptr);
|
||||
}
|
||||
|
||||
bool operator()(double const* const* parameters, double* residuals) const {
|
||||
@@ -115,12 +114,13 @@ class DynamicCostFunctionToFunctor {
|
||||
|
||||
template <typename JetT>
|
||||
bool operator()(JetT const* const* inputs, JetT* output) const {
|
||||
const std::vector<int32>& parameter_block_sizes =
|
||||
const std::vector<int32_t>& parameter_block_sizes =
|
||||
cost_function_->parameter_block_sizes();
|
||||
const int num_parameter_blocks = parameter_block_sizes.size();
|
||||
const int num_parameter_blocks =
|
||||
static_cast<int>(parameter_block_sizes.size());
|
||||
const int num_residuals = cost_function_->num_residuals();
|
||||
const int num_parameters = std::accumulate(parameter_block_sizes.begin(),
|
||||
parameter_block_sizes.end(), 0);
|
||||
const int num_parameters = std::accumulate(
|
||||
parameter_block_sizes.begin(), parameter_block_sizes.end(), 0);
|
||||
|
||||
internal::FixedArray<double> parameters(num_parameters);
|
||||
internal::FixedArray<double*> parameter_blocks(num_parameter_blocks);
|
||||
@@ -130,8 +130,8 @@ class DynamicCostFunctionToFunctor {
|
||||
|
||||
// Build a set of arrays to get the residuals and jacobians from
|
||||
// the CostFunction wrapped by this functor.
|
||||
double* parameter_ptr = parameters.get();
|
||||
double* jacobian_ptr = jacobians.get();
|
||||
double* parameter_ptr = parameters.data();
|
||||
double* jacobian_ptr = jacobians.data();
|
||||
for (int i = 0; i < num_parameter_blocks; ++i) {
|
||||
parameter_blocks[i] = parameter_ptr;
|
||||
jacobian_blocks[i] = jacobian_ptr;
|
||||
@@ -141,9 +141,9 @@ class DynamicCostFunctionToFunctor {
|
||||
jacobian_ptr += num_residuals * parameter_block_sizes[i];
|
||||
}
|
||||
|
||||
if (!cost_function_->Evaluate(parameter_blocks.get(),
|
||||
residuals.get(),
|
||||
jacobian_blocks.get())) {
|
||||
if (!cost_function_->Evaluate(parameter_blocks.data(),
|
||||
residuals.data(),
|
||||
jacobian_blocks.data())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ class DynamicCostFunctionToFunctor {
|
||||
output[i].v.setZero();
|
||||
|
||||
for (int j = 0; j < num_parameter_blocks; ++j) {
|
||||
const int32 block_size = parameter_block_sizes[j];
|
||||
const int32_t block_size = parameter_block_sizes[j];
|
||||
for (int k = 0; k < parameter_block_sizes[j]; ++k) {
|
||||
output[i].v +=
|
||||
jacobian_blocks[j][i * block_size + k] * inputs[j][k].v;
|
||||
@@ -182,7 +182,7 @@ class DynamicCostFunctionToFunctor {
|
||||
}
|
||||
|
||||
private:
|
||||
internal::scoped_ptr<CostFunction> cost_function_;
|
||||
std::unique_ptr<CostFunction> cost_function_;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,7 +30,24 @@
|
||||
// sameeragarwal@google.com (Sameer Agarwal)
|
||||
// thadh@gmail.com (Thad Hughes)
|
||||
// tbennun@gmail.com (Tal Ben-Nun)
|
||||
//
|
||||
|
||||
#ifndef CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
|
||||
#define CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/dynamic_cost_function.h"
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/internal/numeric_diff.h"
|
||||
#include "ceres/internal/parameter_dims.h"
|
||||
#include "ceres/numeric_diff_options.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// This numeric diff implementation differs from the one found in
|
||||
// numeric_diff_cost_function.h by supporting numericdiff on cost
|
||||
// functions with variable numbers of parameters with variable
|
||||
@@ -42,7 +59,9 @@
|
||||
// numeric diff; the expected interface for the cost functors is:
|
||||
//
|
||||
// struct MyCostFunctor {
|
||||
// bool operator()(double const* const* parameters, double* residuals) const {
|
||||
// bool operator()(double const*
|
||||
// const* parameters,
|
||||
// double* residuals) const {
|
||||
// // Use parameters[i] to access the i'th parameter block.
|
||||
// }
|
||||
// }
|
||||
@@ -56,34 +75,14 @@
|
||||
// cost_function.AddParameterBlock(5);
|
||||
// cost_function.AddParameterBlock(10);
|
||||
// cost_function.SetNumResiduals(21);
|
||||
|
||||
#ifndef CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
|
||||
#define CERES_PUBLIC_DYNAMIC_NUMERIC_DIFF_COST_FUNCTION_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/cost_function.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/internal/numeric_diff.h"
|
||||
#include "ceres/numeric_diff_options.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
template <typename CostFunctor, NumericDiffMethodType method = CENTRAL>
|
||||
class DynamicNumericDiffCostFunction : public CostFunction {
|
||||
class DynamicNumericDiffCostFunction : public DynamicCostFunction {
|
||||
public:
|
||||
explicit DynamicNumericDiffCostFunction(
|
||||
const CostFunctor* functor,
|
||||
Ownership ownership = TAKE_OWNERSHIP,
|
||||
const NumericDiffOptions& options = NumericDiffOptions())
|
||||
: functor_(functor),
|
||||
ownership_(ownership),
|
||||
options_(options) {
|
||||
}
|
||||
: functor_(functor), ownership_(ownership), options_(options) {}
|
||||
|
||||
virtual ~DynamicNumericDiffCostFunction() {
|
||||
if (ownership_ != TAKE_OWNERSHIP) {
|
||||
@@ -91,28 +90,22 @@ class DynamicNumericDiffCostFunction : public CostFunction {
|
||||
}
|
||||
}
|
||||
|
||||
void AddParameterBlock(int size) {
|
||||
mutable_parameter_block_sizes()->push_back(size);
|
||||
}
|
||||
|
||||
void SetNumResiduals(int num_residuals) {
|
||||
set_num_residuals(num_residuals);
|
||||
}
|
||||
|
||||
virtual bool Evaluate(double const* const* parameters,
|
||||
double* residuals,
|
||||
double** jacobians) const {
|
||||
bool Evaluate(double const* const* parameters,
|
||||
double* residuals,
|
||||
double** jacobians) const override {
|
||||
using internal::NumericDiff;
|
||||
CHECK_GT(num_residuals(), 0)
|
||||
<< "You must call DynamicNumericDiffCostFunction::SetNumResiduals() "
|
||||
<< "before DynamicNumericDiffCostFunction::Evaluate().";
|
||||
|
||||
const std::vector<int32>& block_sizes = parameter_block_sizes();
|
||||
const std::vector<int32_t>& block_sizes = parameter_block_sizes();
|
||||
CHECK(!block_sizes.empty())
|
||||
<< "You must call DynamicNumericDiffCostFunction::AddParameterBlock() "
|
||||
<< "before DynamicNumericDiffCostFunction::Evaluate().";
|
||||
|
||||
const bool status = EvaluateCostFunctor(parameters, residuals);
|
||||
const bool status =
|
||||
internal::VariadicEvaluate<internal::DynamicParameterDims>(
|
||||
*functor_.get(), parameters, residuals);
|
||||
if (jacobians == NULL || !status) {
|
||||
return status;
|
||||
}
|
||||
@@ -123,8 +116,8 @@ class DynamicNumericDiffCostFunction : public CostFunction {
|
||||
std::vector<double*> parameters_references_copy(block_sizes.size());
|
||||
parameters_references_copy[0] = ¶meters_copy[0];
|
||||
for (size_t block = 1; block < block_sizes.size(); ++block) {
|
||||
parameters_references_copy[block] = parameters_references_copy[block - 1]
|
||||
+ block_sizes[block - 1];
|
||||
parameters_references_copy[block] =
|
||||
parameters_references_copy[block - 1] + block_sizes[block - 1];
|
||||
}
|
||||
|
||||
// Copy the parameters into the local temp space.
|
||||
@@ -136,18 +129,20 @@ class DynamicNumericDiffCostFunction : public CostFunction {
|
||||
|
||||
for (size_t block = 0; block < block_sizes.size(); ++block) {
|
||||
if (jacobians[block] != NULL &&
|
||||
!NumericDiff<CostFunctor, method, DYNAMIC,
|
||||
DYNAMIC, DYNAMIC, DYNAMIC, DYNAMIC, DYNAMIC,
|
||||
DYNAMIC, DYNAMIC, DYNAMIC, DYNAMIC, DYNAMIC,
|
||||
DYNAMIC, DYNAMIC>::EvaluateJacobianForParameterBlock(
|
||||
functor_.get(),
|
||||
residuals,
|
||||
options_,
|
||||
this->num_residuals(),
|
||||
block,
|
||||
block_sizes[block],
|
||||
¶meters_references_copy[0],
|
||||
jacobians[block])) {
|
||||
!NumericDiff<CostFunctor,
|
||||
method,
|
||||
ceres::DYNAMIC,
|
||||
internal::DynamicParameterDims,
|
||||
ceres::DYNAMIC,
|
||||
ceres::DYNAMIC>::
|
||||
EvaluateJacobianForParameterBlock(functor_.get(),
|
||||
residuals,
|
||||
options_,
|
||||
this->num_residuals(),
|
||||
block,
|
||||
block_sizes[block],
|
||||
¶meters_references_copy[0],
|
||||
jacobians[block])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -155,31 +150,7 @@ class DynamicNumericDiffCostFunction : public CostFunction {
|
||||
}
|
||||
|
||||
private:
|
||||
bool EvaluateCostFunctor(double const* const* parameters,
|
||||
double* residuals) const {
|
||||
return EvaluateCostFunctorImpl(functor_.get(),
|
||||
parameters,
|
||||
residuals,
|
||||
functor_.get());
|
||||
}
|
||||
|
||||
// Helper templates to allow evaluation of a functor or a
|
||||
// CostFunction.
|
||||
bool EvaluateCostFunctorImpl(const CostFunctor* functor,
|
||||
double const* const* parameters,
|
||||
double* residuals,
|
||||
const void* /* NOT USED */) const {
|
||||
return (*functor)(parameters, residuals);
|
||||
}
|
||||
|
||||
bool EvaluateCostFunctorImpl(const CostFunctor* functor,
|
||||
double const* const* parameters,
|
||||
double* residuals,
|
||||
const CostFunction* /* NOT USED */) const {
|
||||
return functor->Evaluate(parameters, residuals, NULL);
|
||||
}
|
||||
|
||||
internal::scoped_ptr<const CostFunctor> functor_;
|
||||
std::unique_ptr<const CostFunctor> functor_;
|
||||
Ownership ownership_;
|
||||
NumericDiffOptions options_;
|
||||
};
|
||||
|
80
extern/ceres/include/ceres/evaluation_callback.h
vendored
Normal file
80
extern/ceres/include/ceres/evaluation_callback.h
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: mierle@gmail.com (Keir Mierle)
|
||||
|
||||
#ifndef CERES_PUBLIC_EVALUATION_CALLBACK_H_
|
||||
#define CERES_PUBLIC_EVALUATION_CALLBACK_H_
|
||||
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// Using this callback interface, Ceres can notify you when it is
|
||||
// about to evaluate the residuals or jacobians. With the callback,
|
||||
// you can share computation between residual blocks by doing the
|
||||
// shared computation in PrepareForEvaluation() before Ceres calls
|
||||
// CostFunction::Evaluate(). It also enables caching results between a
|
||||
// pure residual evaluation and a residual & jacobian evaluation, via
|
||||
// the new_evaluation_point argument.
|
||||
//
|
||||
// One use case for this callback is if the cost function compute is
|
||||
// moved to the GPU. In that case, the prepare call does the actual
|
||||
// cost function evaluation, and subsequent calls from Ceres to the
|
||||
// actual cost functions merely copy the results from the GPU onto the
|
||||
// corresponding blocks for Ceres to plug into the solver.
|
||||
//
|
||||
// NOTE: Ceres provides no mechanism to share data other than the
|
||||
// notification from the callback. Users must provide access to
|
||||
// pre-computed shared data to their cost functions behind the scenes;
|
||||
// this all happens without Ceres knowing.
|
||||
//
|
||||
// One approach is to put a pointer to the shared data in each cost
|
||||
// function (recommended) or to use a global shared variable
|
||||
// (discouraged; bug-prone). As far as Ceres is concerned, it is
|
||||
// evaluating cost functions like any other; it just so happens that
|
||||
// behind the scenes the cost functions reuse pre-computed data to
|
||||
// execute faster.
|
||||
class CERES_EXPORT EvaluationCallback {
|
||||
public:
|
||||
virtual ~EvaluationCallback() {}
|
||||
|
||||
// Called before Ceres requests residuals or jacobians for a given setting of
|
||||
// the parameters. User parameters (the double* values provided to the cost
|
||||
// functions) are fixed until the next call to PrepareForEvaluation(). If
|
||||
// new_evaluation_point == true, then this is a new point that is different
|
||||
// from the last evaluated point. Otherwise, it is the same point that was
|
||||
// evaluated previously (either jacobian or residual) and the user can use
|
||||
// cached results from previous evaluations.
|
||||
virtual void PrepareForEvaluation(bool evaluate_jacobians,
|
||||
bool new_evaluation_point) = 0;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_EVALUATION_CALLBACK_H_
|
54
extern/ceres/include/ceres/first_order_function.h
vendored
Normal file
54
extern/ceres/include/ceres/first_order_function.h
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: sameeragarwal@google.com (Sameer Agarwal)
|
||||
|
||||
#ifndef CERES_PUBLIC_FIRST_ORDER_FUNCTION_H_
|
||||
#define CERES_PUBLIC_FIRST_ORDER_FUNCTION_H_
|
||||
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
// A FirstOrderFunction object implements the evaluation of a function
|
||||
// and its gradient.
|
||||
class CERES_EXPORT FirstOrderFunction {
|
||||
public:
|
||||
virtual ~FirstOrderFunction() {}
|
||||
|
||||
// cost is never null. gradient may be null. The return value
|
||||
// indicates whether the evaluation was successful or not.
|
||||
virtual bool Evaluate(const double* const parameters,
|
||||
double* cost,
|
||||
double* gradient) const = 0;
|
||||
virtual int NumParameters() const = 0;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_FIRST_ORDER_FUNCTION_H_
|
23
extern/ceres/include/ceres/gradient_checker.h
vendored
23
extern/ceres/include/ceres/gradient_checker.h
vendored
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,15 +34,14 @@
|
||||
#ifndef CERES_PUBLIC_GRADIENT_CHECKER_H_
|
||||
#define CERES_PUBLIC_GRADIENT_CHECKER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/cost_function.h"
|
||||
#include "ceres/dynamic_numeric_diff_cost_function.h"
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/internal/fixed_array.h"
|
||||
#include "ceres/internal/macros.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/local_parameterization.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
@@ -64,13 +63,13 @@ namespace ceres {
|
||||
//
|
||||
// How to use: Fill in an array of pointers to parameter blocks for your
|
||||
// CostFunction, and then call Probe(). Check that the return value is 'true'.
|
||||
class GradientChecker {
|
||||
class CERES_EXPORT GradientChecker {
|
||||
public:
|
||||
// This will not take ownership of the cost function or local
|
||||
// parameterizations.
|
||||
//
|
||||
// function: The cost function to probe.
|
||||
// local_parameterization: A vector of local parameterizations for each
|
||||
// local_parameterizations: A vector of local parameterizations for each
|
||||
// parameter. May be NULL or contain NULL pointers to indicate that the
|
||||
// respective parameter does not have a local parameterization.
|
||||
// options: Options to use for numerical differentiation.
|
||||
@@ -80,7 +79,7 @@ class GradientChecker {
|
||||
const NumericDiffOptions& options);
|
||||
|
||||
// Contains results from a call to Probe for later inspection.
|
||||
struct ProbeResults {
|
||||
struct CERES_EXPORT ProbeResults {
|
||||
// The return value of the cost function.
|
||||
bool return_value;
|
||||
|
||||
@@ -100,10 +99,10 @@ class GradientChecker {
|
||||
// Derivatives as computed by the cost function in local space.
|
||||
std::vector<Matrix> local_jacobians;
|
||||
|
||||
// Derivatives as computed by nuerical differentiation in local space.
|
||||
// Derivatives as computed by numerical differentiation in local space.
|
||||
std::vector<Matrix> numeric_jacobians;
|
||||
|
||||
// Derivatives as computed by nuerical differentiation in local space.
|
||||
// Derivatives as computed by numerical differentiation in local space.
|
||||
std::vector<Matrix> local_numeric_jacobians;
|
||||
|
||||
// Contains the maximum relative error found in the local Jacobians.
|
||||
@@ -137,11 +136,13 @@ class GradientChecker {
|
||||
ProbeResults* results) const;
|
||||
|
||||
private:
|
||||
CERES_DISALLOW_IMPLICIT_CONSTRUCTORS(GradientChecker);
|
||||
GradientChecker() = delete;
|
||||
GradientChecker(const GradientChecker&) = delete;
|
||||
void operator=(const GradientChecker&) = delete;
|
||||
|
||||
std::vector<const LocalParameterization*> local_parameterizations_;
|
||||
const CostFunction* function_;
|
||||
internal::scoped_ptr<CostFunction> finite_diff_cost_function_;
|
||||
std::unique_ptr<CostFunction> finite_diff_cost_function_;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
25
extern/ceres/include/ceres/gradient_problem.h
vendored
25
extern/ceres/include/ceres/gradient_problem.h
vendored
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,9 +31,10 @@
|
||||
#ifndef CERES_PUBLIC_GRADIENT_PROBLEM_H_
|
||||
#define CERES_PUBLIC_GRADIENT_PROBLEM_H_
|
||||
|
||||
#include "ceres/internal/macros.h"
|
||||
#include <memory>
|
||||
|
||||
#include "ceres/first_order_function.h"
|
||||
#include "ceres/internal/port.h"
|
||||
#include "ceres/internal/scoped_ptr.h"
|
||||
#include "ceres/local_parameterization.h"
|
||||
|
||||
namespace ceres {
|
||||
@@ -105,21 +106,9 @@ class CERES_EXPORT GradientProblem {
|
||||
bool Plus(const double* x, const double* delta, double* x_plus_delta) const;
|
||||
|
||||
private:
|
||||
internal::scoped_ptr<FirstOrderFunction> function_;
|
||||
internal::scoped_ptr<LocalParameterization> parameterization_;
|
||||
internal::scoped_array<double> scratch_;
|
||||
};
|
||||
|
||||
// A FirstOrderFunction object implements the evaluation of a function
|
||||
// and its gradient.
|
||||
class CERES_EXPORT FirstOrderFunction {
|
||||
public:
|
||||
virtual ~FirstOrderFunction() {}
|
||||
// cost is never NULL. gradient may be null.
|
||||
virtual bool Evaluate(const double* const parameters,
|
||||
double* cost,
|
||||
double* gradient) const = 0;
|
||||
virtual int NumParameters() const = 0;
|
||||
std::unique_ptr<FirstOrderFunction> function_;
|
||||
std::unique_ptr<LocalParameterization> parameterization_;
|
||||
std::unique_ptr<double[]> scratch_;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
128
extern/ceres/include/ceres/gradient_problem_solver.h
vendored
128
extern/ceres/include/ceres/gradient_problem_solver.h
vendored
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,11 +34,11 @@
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ceres/internal/macros.h"
|
||||
|
||||
#include "ceres/internal/disable_warnings.h"
|
||||
#include "ceres/internal/port.h"
|
||||
#include "ceres/iteration_callback.h"
|
||||
#include "ceres/types.h"
|
||||
#include "ceres/internal/disable_warnings.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
@@ -54,39 +54,15 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
//
|
||||
// The constants are defined inside types.h
|
||||
struct CERES_EXPORT Options {
|
||||
// Default constructor that sets up a generic sparse problem.
|
||||
Options() {
|
||||
line_search_direction_type = LBFGS;
|
||||
line_search_type = WOLFE;
|
||||
nonlinear_conjugate_gradient_type = FLETCHER_REEVES;
|
||||
max_lbfgs_rank = 20;
|
||||
use_approximate_eigenvalue_bfgs_scaling = false;
|
||||
line_search_interpolation_type = CUBIC;
|
||||
min_line_search_step_size = 1e-9;
|
||||
line_search_sufficient_function_decrease = 1e-4;
|
||||
max_line_search_step_contraction = 1e-3;
|
||||
min_line_search_step_contraction = 0.6;
|
||||
max_num_line_search_step_size_iterations = 20;
|
||||
max_num_line_search_direction_restarts = 5;
|
||||
line_search_sufficient_curvature_decrease = 0.9;
|
||||
max_line_search_step_expansion = 10.0;
|
||||
max_num_iterations = 50;
|
||||
max_solver_time_in_seconds = 1e9;
|
||||
function_tolerance = 1e-6;
|
||||
gradient_tolerance = 1e-10;
|
||||
logging_type = PER_MINIMIZER_ITERATION;
|
||||
minimizer_progress_to_stdout = false;
|
||||
}
|
||||
|
||||
// Returns true if the options struct has a valid
|
||||
// configuration. Returns false otherwise, and fills in *error
|
||||
// with a message describing the problem.
|
||||
bool IsValid(std::string* error) const;
|
||||
|
||||
// Minimizer options ----------------------------------------
|
||||
LineSearchDirectionType line_search_direction_type;
|
||||
LineSearchType line_search_type;
|
||||
NonlinearConjugateGradientType nonlinear_conjugate_gradient_type;
|
||||
LineSearchDirectionType line_search_direction_type = LBFGS;
|
||||
LineSearchType line_search_type = WOLFE;
|
||||
NonlinearConjugateGradientType nonlinear_conjugate_gradient_type = FLETCHER_REEVES;
|
||||
|
||||
// The LBFGS hessian approximation is a low rank approximation to
|
||||
// the inverse of the Hessian matrix. The rank of the
|
||||
@@ -111,8 +87,8 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
// method, please see:
|
||||
//
|
||||
// Nocedal, J. (1980). "Updating Quasi-Newton Matrices with
|
||||
// Limited Storage". Mathematics of Computation 35 (151): 773–782.
|
||||
int max_lbfgs_rank;
|
||||
// Limited Storage". Mathematics of Computation 35 (151): 773-782.
|
||||
int max_lbfgs_rank = 20;
|
||||
|
||||
// As part of the (L)BFGS update step (BFGS) / right-multiply step (L-BFGS),
|
||||
// the initial inverse Hessian approximation is taken to be the Identity.
|
||||
@@ -134,18 +110,18 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
// Oren S.S., Self-scaling variable metric (SSVM) algorithms
|
||||
// Part II: Implementation and experiments, Management Science,
|
||||
// 20(5), 863-874, 1974.
|
||||
bool use_approximate_eigenvalue_bfgs_scaling;
|
||||
bool use_approximate_eigenvalue_bfgs_scaling = false;
|
||||
|
||||
// Degree of the polynomial used to approximate the objective
|
||||
// function. Valid values are BISECTION, QUADRATIC and CUBIC.
|
||||
//
|
||||
// BISECTION corresponds to pure backtracking search with no
|
||||
// interpolation.
|
||||
LineSearchInterpolationType line_search_interpolation_type;
|
||||
LineSearchInterpolationType line_search_interpolation_type = CUBIC;
|
||||
|
||||
// If during the line search, the step_size falls below this
|
||||
// value, it is truncated to zero.
|
||||
double min_line_search_step_size;
|
||||
double min_line_search_step_size = 1e-9;
|
||||
|
||||
// Line search parameters.
|
||||
|
||||
@@ -159,7 +135,7 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
//
|
||||
// f(step_size) <= f(0) + sufficient_decrease * f'(0) * step_size
|
||||
//
|
||||
double line_search_sufficient_function_decrease;
|
||||
double line_search_sufficient_function_decrease = 1e-4;
|
||||
|
||||
// In each iteration of the line search,
|
||||
//
|
||||
@@ -169,7 +145,7 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
//
|
||||
// 0 < max_step_contraction < min_step_contraction < 1
|
||||
//
|
||||
double max_line_search_step_contraction;
|
||||
double max_line_search_step_contraction = 1e-3;
|
||||
|
||||
// In each iteration of the line search,
|
||||
//
|
||||
@@ -179,19 +155,19 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
//
|
||||
// 0 < max_step_contraction < min_step_contraction < 1
|
||||
//
|
||||
double min_line_search_step_contraction;
|
||||
double min_line_search_step_contraction = 0.6;
|
||||
|
||||
// Maximum number of trial step size iterations during each line search,
|
||||
// if a step size satisfying the search conditions cannot be found within
|
||||
// this number of trials, the line search will terminate.
|
||||
int max_num_line_search_step_size_iterations;
|
||||
int max_num_line_search_step_size_iterations = 20;
|
||||
|
||||
// Maximum number of restarts of the line search direction algorithm before
|
||||
// terminating the optimization. Restarts of the line search direction
|
||||
// algorithm occur when the current algorithm fails to produce a new descent
|
||||
// direction. This typically indicates a numerical failure, or a breakdown
|
||||
// in the validity of the approximations used.
|
||||
int max_num_line_search_direction_restarts;
|
||||
int max_num_line_search_direction_restarts = 5;
|
||||
|
||||
// The strong Wolfe conditions consist of the Armijo sufficient
|
||||
// decrease condition, and an additional requirement that the
|
||||
@@ -204,7 +180,7 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
//
|
||||
// Where f() is the line search objective and f'() is the derivative
|
||||
// of f w.r.t step_size (d f / d step_size).
|
||||
double line_search_sufficient_curvature_decrease;
|
||||
double line_search_sufficient_curvature_decrease = 0.9;
|
||||
|
||||
// During the bracketing phase of the Wolfe search, the step size is
|
||||
// increased until either a point satisfying the Wolfe conditions is
|
||||
@@ -215,36 +191,49 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
// new_step_size <= max_step_expansion * step_size.
|
||||
//
|
||||
// By definition for expansion, max_step_expansion > 1.0.
|
||||
double max_line_search_step_expansion;
|
||||
double max_line_search_step_expansion = 10.0;
|
||||
|
||||
// Maximum number of iterations for the minimizer to run for.
|
||||
int max_num_iterations;
|
||||
int max_num_iterations = 50;
|
||||
|
||||
// Maximum time for which the minimizer should run for.
|
||||
double max_solver_time_in_seconds;
|
||||
double max_solver_time_in_seconds = 1e9;
|
||||
|
||||
// Minimizer terminates when
|
||||
//
|
||||
// (new_cost - old_cost) < function_tolerance * old_cost;
|
||||
//
|
||||
double function_tolerance;
|
||||
double function_tolerance = 1e-6;
|
||||
|
||||
// Minimizer terminates when
|
||||
//
|
||||
// max_i |x - Project(Plus(x, -g(x))| < gradient_tolerance
|
||||
//
|
||||
// This value should typically be 1e-4 * function_tolerance.
|
||||
double gradient_tolerance;
|
||||
double gradient_tolerance = 1e-10;
|
||||
|
||||
// Minimizer terminates when
|
||||
//
|
||||
// |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance)
|
||||
//
|
||||
double parameter_tolerance = 1e-8;
|
||||
|
||||
// Logging options ---------------------------------------------------------
|
||||
|
||||
LoggingType logging_type;
|
||||
LoggingType logging_type = PER_MINIMIZER_ITERATION;
|
||||
|
||||
// By default the Minimizer progress is logged to VLOG(1), which
|
||||
// is sent to STDERR depending on the vlog level. If this flag is
|
||||
// set to true, and logging_type is not SILENT, the logging output
|
||||
// is sent to STDOUT.
|
||||
bool minimizer_progress_to_stdout;
|
||||
bool minimizer_progress_to_stdout = false;
|
||||
|
||||
// If true, the user's parameter blocks are updated at the end of
|
||||
// every Minimizer iteration, otherwise they are updated when the
|
||||
// Minimizer terminates. This is useful if, for example, the user
|
||||
// wishes to visualize the state of the optimization every
|
||||
// iteration.
|
||||
bool update_state_every_iteration = false;
|
||||
|
||||
// Callbacks that are executed at the end of each iteration of the
|
||||
// Minimizer. An iteration may terminate midway, either due to
|
||||
@@ -265,8 +254,6 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
};
|
||||
|
||||
struct CERES_EXPORT Summary {
|
||||
Summary();
|
||||
|
||||
// A brief one line description of the state of the solver after
|
||||
// termination.
|
||||
std::string BriefReport() const;
|
||||
@@ -278,65 +265,72 @@ class CERES_EXPORT GradientProblemSolver {
|
||||
bool IsSolutionUsable() const;
|
||||
|
||||
// Minimizer summary -------------------------------------------------
|
||||
TerminationType termination_type;
|
||||
TerminationType termination_type = FAILURE;
|
||||
|
||||
// Reason why the solver terminated.
|
||||
std::string message;
|
||||
std::string message = "ceres::GradientProblemSolve was not called.";
|
||||
|
||||
// Cost of the problem (value of the objective function) before
|
||||
// the optimization.
|
||||
double initial_cost;
|
||||
double initial_cost = -1.0;
|
||||
|
||||
// Cost of the problem (value of the objective function) after the
|
||||
// optimization.
|
||||
double final_cost;
|
||||
double final_cost = -1.0;
|
||||
|
||||
// IterationSummary for each minimizer iteration in order.
|
||||
std::vector<IterationSummary> iterations;
|
||||
|
||||
// Number of times the cost (and not the gradient) was evaluated.
|
||||
int num_cost_evaluations = -1;
|
||||
|
||||
// Number of times the gradient (and the cost) were evaluated.
|
||||
int num_gradient_evaluations = -1;
|
||||
|
||||
// Sum total of all time spent inside Ceres when Solve is called.
|
||||
double total_time_in_seconds;
|
||||
double total_time_in_seconds = -1.0;
|
||||
|
||||
// Time (in seconds) spent evaluating the cost.
|
||||
double cost_evaluation_time_in_seconds;
|
||||
double cost_evaluation_time_in_seconds = -1.0;
|
||||
|
||||
// Time (in seconds) spent evaluating the gradient.
|
||||
double gradient_evaluation_time_in_seconds;
|
||||
double gradient_evaluation_time_in_seconds = -1.0;
|
||||
|
||||
// Time (in seconds) spent minimizing the interpolating polynomial
|
||||
// to compute the next candidate step size as part of a line search.
|
||||
double line_search_polynomial_minimization_time_in_seconds;
|
||||
double line_search_polynomial_minimization_time_in_seconds = -1.0;
|
||||
|
||||
// Number of parameters in the probem.
|
||||
int num_parameters;
|
||||
// Number of parameters in the problem.
|
||||
int num_parameters = -1;
|
||||
|
||||
// Dimension of the tangent space of the problem.
|
||||
int num_local_parameters;
|
||||
int num_local_parameters = -1;
|
||||
|
||||
// Type of line search direction used.
|
||||
LineSearchDirectionType line_search_direction_type;
|
||||
LineSearchDirectionType line_search_direction_type = LBFGS;
|
||||
|
||||
// Type of the line search algorithm used.
|
||||
LineSearchType line_search_type;
|
||||
LineSearchType line_search_type = WOLFE;
|
||||
|
||||
// When performing line search, the degree of the polynomial used
|
||||
// to approximate the objective function.
|
||||
LineSearchInterpolationType line_search_interpolation_type;
|
||||
LineSearchInterpolationType line_search_interpolation_type = CUBIC;
|
||||
|
||||
// If the line search direction is NONLINEAR_CONJUGATE_GRADIENT,
|
||||
// then this indicates the particular variant of non-linear
|
||||
// conjugate gradient used.
|
||||
NonlinearConjugateGradientType nonlinear_conjugate_gradient_type;
|
||||
NonlinearConjugateGradientType nonlinear_conjugate_gradient_type =
|
||||
FLETCHER_REEVES;
|
||||
|
||||
// If the type of the line search direction is LBFGS, then this
|
||||
// indicates the rank of the Hessian approximation.
|
||||
int max_lbfgs_rank;
|
||||
int max_lbfgs_rank = -1;
|
||||
};
|
||||
|
||||
// Once a least squares problem has been built, this function takes
|
||||
// the problem and optimizes it based on the values of the options
|
||||
// parameters. Upon return, a detailed summary of the work performed
|
||||
// by the preprocessor, the non-linear minmizer and the linear
|
||||
// by the preprocessor, the non-linear minimizer and the linear
|
||||
// solver are reported in the summary object.
|
||||
virtual void Solve(const GradientProblemSolver::Options& options,
|
||||
const GradientProblem& problem,
|
||||
|
95
extern/ceres/include/ceres/internal/array_selector.h
vendored
Normal file
95
extern/ceres/include/ceres/internal/array_selector.h
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2020 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: darius.rueckert@fau.de (Darius Rueckert)
|
||||
//
|
||||
|
||||
#ifndef CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
|
||||
#define CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/internal/fixed_array.h"
|
||||
#include "ceres/types.h"
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// StaticFixedArray selects the best array implementation based on template
|
||||
// arguments. If the size is not known at compile-time, pass
|
||||
// ceres::DYNAMIC as a size-template argument.
|
||||
//
|
||||
// Three different containers are selected in different scenarios:
|
||||
//
|
||||
// num_elements == DYNAMIC:
|
||||
// -> ceres::internal::FixedArray<T, max_stack_size>(size)
|
||||
|
||||
// num_elements != DYNAMIC && num_elements <= max_stack_size
|
||||
// -> std::array<T,num_elements>
|
||||
|
||||
// num_elements != DYNAMIC && num_elements > max_stack_size
|
||||
// -> std::vector<T>(num_elements)
|
||||
//
|
||||
template <typename T,
|
||||
int num_elements,
|
||||
int max_num_elements_on_stack,
|
||||
bool dynamic = (num_elements == DYNAMIC),
|
||||
bool fits_on_stack = (num_elements <= max_num_elements_on_stack)>
|
||||
struct ArraySelector {};
|
||||
|
||||
template <typename T,
|
||||
int num_elements,
|
||||
int max_num_elements_on_stack,
|
||||
bool fits_on_stack>
|
||||
struct ArraySelector<T,
|
||||
num_elements,
|
||||
max_num_elements_on_stack,
|
||||
true,
|
||||
fits_on_stack>
|
||||
: ceres::internal::FixedArray<T, max_num_elements_on_stack> {
|
||||
ArraySelector(int s)
|
||||
: ceres::internal::FixedArray<T, max_num_elements_on_stack>(s) {}
|
||||
};
|
||||
|
||||
template <typename T, int num_elements, int max_num_elements_on_stack>
|
||||
struct ArraySelector<T, num_elements, max_num_elements_on_stack, false, true>
|
||||
: std::array<T, num_elements> {
|
||||
ArraySelector(int s) { CHECK_EQ(s, num_elements); }
|
||||
};
|
||||
|
||||
template <typename T, int num_elements, int max_num_elements_on_stack>
|
||||
struct ArraySelector<T, num_elements, max_num_elements_on_stack, false, false>
|
||||
: std::vector<T> {
|
||||
ArraySelector(int s) : std::vector<T>(s) { CHECK_EQ(s, num_elements); }
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_INTERNAL_ARRAY_SELECTOR_H_
|
301
extern/ceres/include/ceres/internal/autodiff.h
vendored
301
extern/ceres/include/ceres/internal/autodiff.h
vendored
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,10 +30,10 @@
|
||||
//
|
||||
// Computation of the Jacobian matrix for vector-valued functions of multiple
|
||||
// variables, using automatic differentiation based on the implementation of
|
||||
// dual numbers in jet.h. Before reading the rest of this file, it is adivsable
|
||||
// dual numbers in jet.h. Before reading the rest of this file, it is advisable
|
||||
// to read jet.h's header comment in detail.
|
||||
//
|
||||
// The helper wrapper AutoDiff::Differentiate() computes the jacobian of
|
||||
// The helper wrapper AutoDifferentiate() computes the jacobian of
|
||||
// functors with templated operator() taking this form:
|
||||
//
|
||||
// struct F {
|
||||
@@ -57,7 +57,7 @@
|
||||
// [ * ]
|
||||
//
|
||||
// Similar to the 2-parameter example for f described in jet.h, computing the
|
||||
// jacobian dy/dx is done by substutiting a suitable jet object for x and all
|
||||
// jacobian dy/dx is done by substituting a suitable jet object for x and all
|
||||
// intermediate steps of the computation of F. Since x is has 4 dimensions, use
|
||||
// a Jet<double, 4>.
|
||||
//
|
||||
@@ -142,16 +142,33 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "ceres/jet.h"
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
#include "ceres/internal/array_selector.h"
|
||||
#include "ceres/internal/eigen.h"
|
||||
#include "ceres/internal/fixed_array.h"
|
||||
#include "ceres/internal/parameter_dims.h"
|
||||
#include "ceres/internal/variadic_evaluate.h"
|
||||
#include "ceres/jet.h"
|
||||
#include "ceres/types.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
// If the number of parameters exceeds this values, the corresponding jets are
|
||||
// placed on the heap. This will reduce performance by a factor of 2-5 on
|
||||
// current compilers.
|
||||
#ifndef CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK
|
||||
#define CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK 50
|
||||
#endif
|
||||
|
||||
#ifndef CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK
|
||||
#define CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK 20
|
||||
#endif
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// Extends src by a 1st order pertubation for every dimension and puts it in
|
||||
// Extends src by a 1st order perturbation for every dimension and puts it in
|
||||
// dst. The size of src is N. Since this is also used for perturbations in
|
||||
// blocked arrays, offset is used to shift which part of the jet the
|
||||
// perturbation occurs. This is used to set up the extended x augmented by an
|
||||
@@ -165,21 +182,62 @@ namespace internal {
|
||||
//
|
||||
// is what would get put in dst if N was 3, offset was 3, and the jet type JetT
|
||||
// was 8-dimensional.
|
||||
template <typename JetT, typename T, int N>
|
||||
inline void Make1stOrderPerturbation(int offset, const T* src, JetT* dst) {
|
||||
DCHECK(src);
|
||||
DCHECK(dst);
|
||||
for (int j = 0; j < N; ++j) {
|
||||
dst[j].a = src[j];
|
||||
dst[j].v.setZero();
|
||||
dst[j].v[offset + j] = T(1.0);
|
||||
template <int j, int N, int Offset, typename T, typename JetT>
|
||||
struct Make1stOrderPerturbation {
|
||||
public:
|
||||
inline static void Apply(const T* src, JetT* dst) {
|
||||
if (j == 0) {
|
||||
DCHECK(src);
|
||||
DCHECK(dst);
|
||||
}
|
||||
dst[j] = JetT(src[j], j + Offset);
|
||||
Make1stOrderPerturbation<j + 1, N, Offset, T, JetT>::Apply(src, dst);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <int N, int Offset, typename T, typename JetT>
|
||||
struct Make1stOrderPerturbation<N, N, Offset, T, JetT> {
|
||||
public:
|
||||
static void Apply(const T* /*src*/, JetT* /*dst*/) {}
|
||||
};
|
||||
|
||||
// Calls Make1stOrderPerturbation for every parameter block.
|
||||
//
|
||||
// Example:
|
||||
// If one having three parameter blocks with dimensions (3, 2, 4), the call
|
||||
// Make1stOrderPerturbations<integer_sequence<3, 2, 4>::Apply(params, x);
|
||||
// will result in the following calls to Make1stOrderPerturbation:
|
||||
// Make1stOrderPerturbation<0, 3, 0>::Apply(params[0], x + 0);
|
||||
// Make1stOrderPerturbation<0, 2, 3>::Apply(params[1], x + 3);
|
||||
// Make1stOrderPerturbation<0, 4, 5>::Apply(params[2], x + 5);
|
||||
template <typename Seq, int ParameterIdx = 0, int Offset = 0>
|
||||
struct Make1stOrderPerturbations;
|
||||
|
||||
template <int N, int... Ns, int ParameterIdx, int Offset>
|
||||
struct Make1stOrderPerturbations<std::integer_sequence<int, N, Ns...>,
|
||||
ParameterIdx,
|
||||
Offset> {
|
||||
template <typename T, typename JetT>
|
||||
inline static void Apply(T const* const* parameters, JetT* x) {
|
||||
Make1stOrderPerturbation<0, N, Offset, T, JetT>::Apply(
|
||||
parameters[ParameterIdx], x + Offset);
|
||||
Make1stOrderPerturbations<std::integer_sequence<int, Ns...>,
|
||||
ParameterIdx + 1,
|
||||
Offset + N>::Apply(parameters, x);
|
||||
}
|
||||
};
|
||||
|
||||
// End of 'recursion'. Nothing more to do.
|
||||
template <int ParameterIdx, int Total>
|
||||
struct Make1stOrderPerturbations<std::integer_sequence<int>, ParameterIdx, Total> {
|
||||
template <typename T, typename JetT>
|
||||
static void Apply(T const* const* /* NOT USED */, JetT* /* NOT USED */) {}
|
||||
};
|
||||
|
||||
// Takes the 0th order part of src, assumed to be a Jet type, and puts it in
|
||||
// dst. This is used to pick out the "vector" part of the extended y.
|
||||
template <typename JetT, typename T>
|
||||
inline void Take0thOrderPart(int M, const JetT *src, T dst) {
|
||||
inline void Take0thOrderPart(int M, const JetT* src, T dst) {
|
||||
DCHECK(src);
|
||||
for (int i = 0; i < M; ++i) {
|
||||
dst[i] = src[i].a;
|
||||
@@ -188,129 +246,118 @@ inline void Take0thOrderPart(int M, const JetT *src, T dst) {
|
||||
|
||||
// Takes N 1st order parts, starting at index N0, and puts them in the M x N
|
||||
// matrix 'dst'. This is used to pick out the "matrix" parts of the extended y.
|
||||
template <typename JetT, typename T, int N0, int N>
|
||||
inline void Take1stOrderPart(const int M, const JetT *src, T *dst) {
|
||||
template <int N0, int N, typename JetT, typename T>
|
||||
inline void Take1stOrderPart(const int M, const JetT* src, T* dst) {
|
||||
DCHECK(src);
|
||||
DCHECK(dst);
|
||||
for (int i = 0; i < M; ++i) {
|
||||
Eigen::Map<Eigen::Matrix<T, N, 1> >(dst + N * i, N) =
|
||||
Eigen::Map<Eigen::Matrix<T, N, 1>>(dst + N * i, N) =
|
||||
src[i].v.template segment<N>(N0);
|
||||
}
|
||||
}
|
||||
|
||||
// This is in a struct because default template parameters on a
|
||||
// function are not supported in C++03 (though it is available in
|
||||
// C++0x). N0 through N5 are the dimension of the input arguments to
|
||||
// the user supplied functor.
|
||||
template <typename Functor, typename T,
|
||||
int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0,
|
||||
int N5 = 0, int N6 = 0, int N7 = 0, int N8 = 0, int N9 = 0>
|
||||
struct AutoDiff {
|
||||
static bool Differentiate(const Functor& functor,
|
||||
T const *const *parameters,
|
||||
int num_outputs,
|
||||
T *function_value,
|
||||
T **jacobians) {
|
||||
// This block breaks the 80 column rule to keep it somewhat readable.
|
||||
DCHECK_GT(num_outputs, 0);
|
||||
DCHECK((!N1 && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
|
||||
((N1 > 0) && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
|
||||
((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5 && !N6 && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && !N6 && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && !N7 && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && !N8 && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && !N9) || // NOLINT
|
||||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && (N9 > 0))) // NOLINT
|
||||
<< "Zero block cannot precede a non-zero block. Block sizes are "
|
||||
<< "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", "
|
||||
<< N3 << ", " << N4 << ", " << N5 << ", " << N6 << ", " << N7 << ", "
|
||||
<< N8 << ", " << N9;
|
||||
// Calls Take1stOrderPart for every parameter block.
|
||||
//
|
||||
// Example:
|
||||
// If one having three parameter blocks with dimensions (3, 2, 4), the call
|
||||
// Take1stOrderParts<integer_sequence<3, 2, 4>::Apply(num_outputs,
|
||||
// output,
|
||||
// jacobians);
|
||||
// will result in the following calls to Take1stOrderPart:
|
||||
// if (jacobians[0]) {
|
||||
// Take1stOrderPart<0, 3>(num_outputs, output, jacobians[0]);
|
||||
// }
|
||||
// if (jacobians[1]) {
|
||||
// Take1stOrderPart<3, 2>(num_outputs, output, jacobians[1]);
|
||||
// }
|
||||
// if (jacobians[2]) {
|
||||
// Take1stOrderPart<5, 4>(num_outputs, output, jacobians[2]);
|
||||
// }
|
||||
template <typename Seq, int ParameterIdx = 0, int Offset = 0>
|
||||
struct Take1stOrderParts;
|
||||
|
||||
typedef Jet<T, N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9> JetT;
|
||||
FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(
|
||||
N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9 + num_outputs);
|
||||
|
||||
// These are the positions of the respective jets in the fixed array x.
|
||||
const int jet0 = 0;
|
||||
const int jet1 = N0;
|
||||
const int jet2 = N0 + N1;
|
||||
const int jet3 = N0 + N1 + N2;
|
||||
const int jet4 = N0 + N1 + N2 + N3;
|
||||
const int jet5 = N0 + N1 + N2 + N3 + N4;
|
||||
const int jet6 = N0 + N1 + N2 + N3 + N4 + N5;
|
||||
const int jet7 = N0 + N1 + N2 + N3 + N4 + N5 + N6;
|
||||
const int jet8 = N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7;
|
||||
const int jet9 = N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8;
|
||||
|
||||
const JetT *unpacked_parameters[10] = {
|
||||
x.get() + jet0,
|
||||
x.get() + jet1,
|
||||
x.get() + jet2,
|
||||
x.get() + jet3,
|
||||
x.get() + jet4,
|
||||
x.get() + jet5,
|
||||
x.get() + jet6,
|
||||
x.get() + jet7,
|
||||
x.get() + jet8,
|
||||
x.get() + jet9,
|
||||
};
|
||||
|
||||
JetT* output = x.get() + N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9;
|
||||
|
||||
#define CERES_MAKE_1ST_ORDER_PERTURBATION(i) \
|
||||
if (N ## i) { \
|
||||
internal::Make1stOrderPerturbation<JetT, T, N ## i>( \
|
||||
jet ## i, \
|
||||
parameters[i], \
|
||||
x.get() + jet ## i); \
|
||||
template <int N, int... Ns, int ParameterIdx, int Offset>
|
||||
struct Take1stOrderParts<std::integer_sequence<int, N, Ns...>,
|
||||
ParameterIdx,
|
||||
Offset> {
|
||||
template <typename JetT, typename T>
|
||||
inline static void Apply(int num_outputs, JetT* output, T** jacobians) {
|
||||
if (jacobians[ParameterIdx]) {
|
||||
Take1stOrderPart<Offset, N>(num_outputs, output, jacobians[ParameterIdx]);
|
||||
}
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(0);
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(1);
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(2);
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(3);
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(4);
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(5);
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(6);
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(7);
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(8);
|
||||
CERES_MAKE_1ST_ORDER_PERTURBATION(9);
|
||||
#undef CERES_MAKE_1ST_ORDER_PERTURBATION
|
||||
|
||||
if (!VariadicEvaluate<Functor, JetT,
|
||||
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Call(
|
||||
functor, unpacked_parameters, output)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
internal::Take0thOrderPart(num_outputs, output, function_value);
|
||||
|
||||
#define CERES_TAKE_1ST_ORDER_PERTURBATION(i) \
|
||||
if (N ## i) { \
|
||||
if (jacobians[i]) { \
|
||||
internal::Take1stOrderPart<JetT, T, \
|
||||
jet ## i, \
|
||||
N ## i>(num_outputs, \
|
||||
output, \
|
||||
jacobians[i]); \
|
||||
} \
|
||||
}
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(0);
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(1);
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(2);
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(3);
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(4);
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(5);
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(6);
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(7);
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(8);
|
||||
CERES_TAKE_1ST_ORDER_PERTURBATION(9);
|
||||
#undef CERES_TAKE_1ST_ORDER_PERTURBATION
|
||||
return true;
|
||||
Take1stOrderParts<std::integer_sequence<int, Ns...>,
|
||||
ParameterIdx + 1,
|
||||
Offset + N>::Apply(num_outputs, output, jacobians);
|
||||
}
|
||||
};
|
||||
|
||||
// End of 'recursion'. Nothing more to do.
|
||||
template <int ParameterIdx, int Offset>
|
||||
struct Take1stOrderParts<std::integer_sequence<int>, ParameterIdx, Offset> {
|
||||
template <typename T, typename JetT>
|
||||
static void Apply(int /* NOT USED*/,
|
||||
JetT* /* NOT USED*/,
|
||||
T** /* NOT USED */) {}
|
||||
};
|
||||
|
||||
template <int kNumResiduals,
|
||||
typename ParameterDims,
|
||||
typename Functor,
|
||||
typename T>
|
||||
inline bool AutoDifferentiate(const Functor& functor,
|
||||
T const* const* parameters,
|
||||
int dynamic_num_outputs,
|
||||
T* function_value,
|
||||
T** jacobians) {
|
||||
typedef Jet<T, ParameterDims::kNumParameters> JetT;
|
||||
using Parameters = typename ParameterDims::Parameters;
|
||||
|
||||
if (kNumResiduals != DYNAMIC) {
|
||||
DCHECK_EQ(kNumResiduals, dynamic_num_outputs);
|
||||
}
|
||||
|
||||
ArraySelector<JetT,
|
||||
ParameterDims::kNumParameters,
|
||||
CERES_AUTODIFF_MAX_PARAMETERS_ON_STACK>
|
||||
parameters_as_jets(ParameterDims::kNumParameters);
|
||||
|
||||
// Pointers to the beginning of each parameter block
|
||||
std::array<JetT*, ParameterDims::kNumParameterBlocks> unpacked_parameters =
|
||||
ParameterDims::GetUnpackedParameters(parameters_as_jets.data());
|
||||
|
||||
// If the number of residuals is fixed, we use the template argument as the
|
||||
// number of outputs. Otherwise we use the num_outputs parameter. Note: The
|
||||
// ?-operator here is compile-time evaluated, therefore num_outputs is also
|
||||
// a compile-time constant for functors with fixed residuals.
|
||||
const int num_outputs =
|
||||
kNumResiduals == DYNAMIC ? dynamic_num_outputs : kNumResiduals;
|
||||
DCHECK_GT(num_outputs, 0);
|
||||
|
||||
ArraySelector<JetT, kNumResiduals, CERES_AUTODIFF_MAX_RESIDUALS_ON_STACK>
|
||||
residuals_as_jets(num_outputs);
|
||||
|
||||
// Invalidate the output Jets, so that we can detect if the user
|
||||
// did not assign values to all of them.
|
||||
for (int i = 0; i < num_outputs; ++i) {
|
||||
residuals_as_jets[i].a = kImpossibleValue;
|
||||
residuals_as_jets[i].v.setConstant(kImpossibleValue);
|
||||
}
|
||||
|
||||
Make1stOrderPerturbations<Parameters>::Apply(parameters,
|
||||
parameters_as_jets.data());
|
||||
|
||||
if (!VariadicEvaluate<ParameterDims>(
|
||||
functor, unpacked_parameters.data(), residuals_as_jets.data())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Take0thOrderPart(num_outputs, residuals_as_jets.data(), function_value);
|
||||
Take1stOrderParts<Parameters>::Apply(
|
||||
num_outputs, residuals_as_jets.data(), jacobians);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
|
@@ -35,7 +35,7 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( push )
|
||||
// Disable the warning C4251 which is trigerred by stl classes in
|
||||
// Disable the warning C4251 which is triggered by stl classes in
|
||||
// Ceres' public interface. To quote MSDN: "C4251 can be ignored "
|
||||
// "if you are deriving from a type in the Standard C++ Library"
|
||||
#pragma warning( disable : 4251 )
|
||||
|
39
extern/ceres/include/ceres/internal/eigen.h
vendored
39
extern/ceres/include/ceres/internal/eigen.h
vendored
@@ -52,40 +52,27 @@ typedef Eigen::Matrix<double,
|
||||
Eigen::ColMajor> ColMajorMatrix;
|
||||
|
||||
typedef Eigen::Map<ColMajorMatrix, 0,
|
||||
Eigen::Stride<Eigen::Dynamic, 1> > ColMajorMatrixRef;
|
||||
Eigen::Stride<Eigen::Dynamic, 1>> ColMajorMatrixRef;
|
||||
|
||||
typedef Eigen::Map<const ColMajorMatrix,
|
||||
0,
|
||||
Eigen::Stride<Eigen::Dynamic, 1> > ConstColMajorMatrixRef;
|
||||
|
||||
|
||||
Eigen::Stride<Eigen::Dynamic, 1>> ConstColMajorMatrixRef;
|
||||
|
||||
// C++ does not support templated typdefs, thus the need for this
|
||||
// struct so that we can support statically sized Matrix and Maps.
|
||||
template <int num_rows = Eigen::Dynamic, int num_cols = Eigen::Dynamic>
|
||||
template <int num_rows = Eigen::Dynamic, int num_cols = Eigen::Dynamic>
|
||||
struct EigenTypes {
|
||||
typedef Eigen::Matrix <double, num_rows, num_cols, Eigen::RowMajor>
|
||||
Matrix;
|
||||
typedef Eigen::Matrix<double,
|
||||
num_rows,
|
||||
num_cols,
|
||||
num_cols == 1 ? Eigen::ColMajor : Eigen::RowMajor>
|
||||
Matrix;
|
||||
|
||||
typedef Eigen::Map<
|
||||
Eigen::Matrix<double, num_rows, num_cols, Eigen::RowMajor> >
|
||||
MatrixRef;
|
||||
|
||||
typedef Eigen::Matrix <double, num_rows, 1>
|
||||
Vector;
|
||||
|
||||
typedef Eigen::Map <
|
||||
Eigen::Matrix<double, num_rows, 1> >
|
||||
VectorRef;
|
||||
|
||||
|
||||
typedef Eigen::Map<
|
||||
const Eigen::Matrix<double, num_rows, num_cols, Eigen::RowMajor> >
|
||||
ConstMatrixRef;
|
||||
|
||||
typedef Eigen::Map <
|
||||
const Eigen::Matrix<double, num_rows, 1> >
|
||||
ConstVectorRef;
|
||||
typedef Eigen::Map<Matrix> MatrixRef;
|
||||
typedef Eigen::Map<const Matrix> ConstMatrixRef;
|
||||
typedef Eigen::Matrix<double, num_rows, 1> Vector;
|
||||
typedef Eigen::Map<Eigen::Matrix<double, num_rows, 1>> VectorRef;
|
||||
typedef Eigen::Map<const Eigen::Matrix<double, num_rows, 1>> ConstVectorRef;
|
||||
};
|
||||
|
||||
} // namespace ceres
|
||||
|
575
extern/ceres/include/ceres/internal/fixed_array.h
vendored
575
extern/ceres/include/ceres/internal/fixed_array.h
vendored
@@ -1,189 +1,466 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
// Copyright 2018 The Abseil Authors.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Author: rennie@google.com (Jeffrey Rennie)
|
||||
// Author: sanjay@google.com (Sanjay Ghemawat) -- renamed to FixedArray
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: fixed_array.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// A `FixedArray<T>` represents a non-resizable array of `T` where the length of
|
||||
// the array can be determined at run-time. It is a good replacement for
|
||||
// non-standard and deprecated uses of `alloca()` and variable length arrays
|
||||
// within the GCC extension. (See
|
||||
// https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html).
|
||||
//
|
||||
// `FixedArray` allocates small arrays inline, keeping performance fast by
|
||||
// avoiding heap operations. It also helps reduce the chances of
|
||||
// accidentally overflowing your stack if large input is passed to
|
||||
// your function.
|
||||
|
||||
#ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
|
||||
#define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include "Eigen/Core"
|
||||
#include "ceres/internal/macros.h"
|
||||
#include "ceres/internal/manual_constructor.h"
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#include <Eigen/Core> // For Eigen::aligned_allocator
|
||||
|
||||
#include "ceres/internal/memory.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// A FixedArray<T> represents a non-resizable array of T where the
|
||||
// length of the array does not need to be a compile time constant.
|
||||
//
|
||||
// FixedArray allocates small arrays inline, and large arrays on
|
||||
// the heap. It is a good replacement for non-standard and deprecated
|
||||
// uses of alloca() and variable length arrays (a GCC extension).
|
||||
//
|
||||
// FixedArray keeps performance fast for small arrays, because it
|
||||
// avoids heap operations. It also helps reduce the chances of
|
||||
// accidentally overflowing your stack if large input is passed to
|
||||
// your function.
|
||||
//
|
||||
// Also, FixedArray is useful for writing portable code. Not all
|
||||
// compilers support arrays of dynamic size.
|
||||
constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
|
||||
|
||||
// Most users should not specify an inline_elements argument and let
|
||||
// FixedArray<> automatically determine the number of elements
|
||||
// to store inline based on sizeof(T).
|
||||
// The default fixed array allocator.
|
||||
//
|
||||
// If inline_elements is specified, the FixedArray<> implementation
|
||||
// will store arrays of length <= inline_elements inline.
|
||||
//
|
||||
// Finally note that unlike vector<T> FixedArray<T> will not zero-initialize
|
||||
// simple types like int, double, bool, etc.
|
||||
//
|
||||
// Non-POD types will be default-initialized just like regular vectors or
|
||||
// arrays.
|
||||
// As one can not easily detect if a struct contains or inherits from a fixed
|
||||
// size Eigen type, to be safe the Eigen::aligned_allocator is used by default.
|
||||
// But trivial types can never contain Eigen types, so std::allocator is used to
|
||||
// safe some heap memory.
|
||||
template <typename T>
|
||||
using FixedArrayDefaultAllocator =
|
||||
typename std::conditional<std::is_trivial<T>::value,
|
||||
std::allocator<T>,
|
||||
Eigen::aligned_allocator<T>>::type;
|
||||
|
||||
#if defined(_WIN64)
|
||||
typedef __int64 ssize_t;
|
||||
#elif defined(_WIN32)
|
||||
typedef __int32 ssize_t;
|
||||
#endif
|
||||
|
||||
template <typename T, ssize_t inline_elements = -1>
|
||||
// -----------------------------------------------------------------------------
|
||||
// FixedArray
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// A `FixedArray` provides a run-time fixed-size array, allocating a small array
|
||||
// inline for efficiency.
|
||||
//
|
||||
// Most users should not specify an `inline_elements` argument and let
|
||||
// `FixedArray` automatically determine the number of elements
|
||||
// to store inline based on `sizeof(T)`. If `inline_elements` is specified, the
|
||||
// `FixedArray` implementation will use inline storage for arrays with a
|
||||
// length <= `inline_elements`.
|
||||
//
|
||||
// Note that a `FixedArray` constructed with a `size_type` argument will
|
||||
// default-initialize its values by leaving trivially constructible types
|
||||
// uninitialized (e.g. int, int[4], double), and others default-constructed.
|
||||
// This matches the behavior of c-style arrays and `std::array`, but not
|
||||
// `std::vector`.
|
||||
//
|
||||
// Note that `FixedArray` does not provide a public allocator; if it requires a
|
||||
// heap allocation, it will do so with global `::operator new[]()` and
|
||||
// `::operator delete[]()`, even if T provides class-scope overrides for these
|
||||
// operators.
|
||||
template <typename T,
|
||||
size_t N = kFixedArrayUseDefault,
|
||||
typename A = FixedArrayDefaultAllocator<T>>
|
||||
class FixedArray {
|
||||
static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,
|
||||
"Arrays with unknown bounds cannot be used with FixedArray.");
|
||||
|
||||
static constexpr size_t kInlineBytesDefault = 256;
|
||||
|
||||
using AllocatorTraits = std::allocator_traits<A>;
|
||||
// std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,
|
||||
// but this seems to be mostly pedantic.
|
||||
template <typename Iterator>
|
||||
using EnableIfForwardIterator = typename std::enable_if<std::is_convertible<
|
||||
typename std::iterator_traits<Iterator>::iterator_category,
|
||||
std::forward_iterator_tag>::value>::type;
|
||||
static constexpr bool DefaultConstructorIsNonTrivial() {
|
||||
return !std::is_trivially_default_constructible<StorageElement>::value;
|
||||
}
|
||||
|
||||
public:
|
||||
// For playing nicely with stl:
|
||||
typedef T value_type;
|
||||
typedef T* iterator;
|
||||
typedef T const* const_iterator;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef size_t size_type;
|
||||
using allocator_type = typename AllocatorTraits::allocator_type;
|
||||
using value_type = typename AllocatorTraits::value_type;
|
||||
using pointer = typename AllocatorTraits::pointer;
|
||||
using const_pointer = typename AllocatorTraits::const_pointer;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using size_type = typename AllocatorTraits::size_type;
|
||||
using difference_type = typename AllocatorTraits::difference_type;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
// REQUIRES: n >= 0
|
||||
// Creates an array object that can store "n" elements.
|
||||
static constexpr size_type inline_elements =
|
||||
(N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)
|
||||
: static_cast<size_type>(N));
|
||||
|
||||
FixedArray(const FixedArray& other,
|
||||
const allocator_type& a = allocator_type())
|
||||
: FixedArray(other.begin(), other.end(), a) {}
|
||||
|
||||
FixedArray(FixedArray&& other, const allocator_type& a = allocator_type())
|
||||
: FixedArray(std::make_move_iterator(other.begin()),
|
||||
std::make_move_iterator(other.end()),
|
||||
a) {}
|
||||
|
||||
// Creates an array object that can store `n` elements.
|
||||
// Note that trivially constructible elements will be uninitialized.
|
||||
explicit FixedArray(size_type n, const allocator_type& a = allocator_type())
|
||||
: storage_(n, a) {
|
||||
if (DefaultConstructorIsNonTrivial()) {
|
||||
ConstructRange(storage_.alloc(), storage_.begin(), storage_.end());
|
||||
}
|
||||
}
|
||||
|
||||
// Creates an array initialized with `n` copies of `val`.
|
||||
FixedArray(size_type n,
|
||||
const value_type& val,
|
||||
const allocator_type& a = allocator_type())
|
||||
: storage_(n, a) {
|
||||
ConstructRange(storage_.alloc(), storage_.begin(), storage_.end(), val);
|
||||
}
|
||||
|
||||
// Creates an array initialized with the size and contents of `init_list`.
|
||||
FixedArray(std::initializer_list<value_type> init_list,
|
||||
const allocator_type& a = allocator_type())
|
||||
: FixedArray(init_list.begin(), init_list.end(), a) {}
|
||||
|
||||
// Creates an array initialized with the elements from the input
|
||||
// range. The array's size will always be `std::distance(first, last)`.
|
||||
// REQUIRES: Iterator must be a forward_iterator or better.
|
||||
template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr>
|
||||
FixedArray(Iterator first,
|
||||
Iterator last,
|
||||
const allocator_type& a = allocator_type())
|
||||
: storage_(std::distance(first, last), a) {
|
||||
CopyRange(storage_.alloc(), storage_.begin(), first, last);
|
||||
}
|
||||
|
||||
~FixedArray() noexcept {
|
||||
for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {
|
||||
AllocatorTraits::destroy(storage_.alloc(), cur);
|
||||
}
|
||||
}
|
||||
|
||||
// Assignments are deleted because they break the invariant that the size of a
|
||||
// `FixedArray` never changes.
|
||||
void operator=(FixedArray&&) = delete;
|
||||
void operator=(const FixedArray&) = delete;
|
||||
|
||||
// FixedArray::size()
|
||||
//
|
||||
// FixedArray<T> will not zero-initialiaze POD (simple) types like int,
|
||||
// double, bool, etc.
|
||||
// Non-POD types will be default-initialized just like regular vectors or
|
||||
// arrays.
|
||||
explicit FixedArray(size_type n);
|
||||
// Returns the length of the fixed array.
|
||||
size_type size() const { return storage_.size(); }
|
||||
|
||||
// Releases any resources.
|
||||
~FixedArray();
|
||||
|
||||
// Returns the length of the array.
|
||||
inline size_type size() const { return size_; }
|
||||
|
||||
// Returns the memory size of the array in bytes.
|
||||
inline size_t memsize() const { return size_ * sizeof(T); }
|
||||
|
||||
// Returns a pointer to the underlying element array.
|
||||
inline const T* get() const { return &array_[0].element; }
|
||||
inline T* get() { return &array_[0].element; }
|
||||
|
||||
// REQUIRES: 0 <= i < size()
|
||||
// Returns a reference to the "i"th element.
|
||||
inline T& operator[](size_type i) {
|
||||
DCHECK_LT(i, size_);
|
||||
return array_[i].element;
|
||||
// FixedArray::max_size()
|
||||
//
|
||||
// Returns the largest possible value of `std::distance(begin(), end())` for a
|
||||
// `FixedArray<T>`. This is equivalent to the most possible addressable bytes
|
||||
// over the number of bytes taken by T.
|
||||
constexpr size_type max_size() const {
|
||||
return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
|
||||
}
|
||||
|
||||
// FixedArray::empty()
|
||||
//
|
||||
// Returns whether or not the fixed array is empty.
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
// FixedArray::memsize()
|
||||
//
|
||||
// Returns the memory size of the fixed array in bytes.
|
||||
size_t memsize() const { return size() * sizeof(value_type); }
|
||||
|
||||
// FixedArray::data()
|
||||
//
|
||||
// Returns a const T* pointer to elements of the `FixedArray`. This pointer
|
||||
// can be used to access (but not modify) the contained elements.
|
||||
const_pointer data() const { return AsValueType(storage_.begin()); }
|
||||
|
||||
// Overload of FixedArray::data() to return a T* pointer to elements of the
|
||||
// fixed array. This pointer can be used to access and modify the contained
|
||||
// elements.
|
||||
pointer data() { return AsValueType(storage_.begin()); }
|
||||
|
||||
// FixedArray::operator[]
|
||||
//
|
||||
// Returns a reference the ith element of the fixed array.
|
||||
// REQUIRES: 0 <= i < size()
|
||||
// Returns a reference to the "i"th element.
|
||||
inline const T& operator[](size_type i) const {
|
||||
DCHECK_LT(i, size_);
|
||||
return array_[i].element;
|
||||
reference operator[](size_type i) {
|
||||
DCHECK_LT(i, size());
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
inline iterator begin() { return &array_[0].element; }
|
||||
inline iterator end() { return &array_[size_].element; }
|
||||
// Overload of FixedArray::operator()[] to return a const reference to the
|
||||
// ith element of the fixed array.
|
||||
// REQUIRES: 0 <= i < size()
|
||||
const_reference operator[](size_type i) const {
|
||||
DCHECK_LT(i, size());
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
inline const_iterator begin() const { return &array_[0].element; }
|
||||
inline const_iterator end() const { return &array_[size_].element; }
|
||||
// FixedArray::front()
|
||||
//
|
||||
// Returns a reference to the first element of the fixed array.
|
||||
reference front() { return *begin(); }
|
||||
|
||||
// Overload of FixedArray::front() to return a reference to the first element
|
||||
// of a fixed array of const values.
|
||||
const_reference front() const { return *begin(); }
|
||||
|
||||
// FixedArray::back()
|
||||
//
|
||||
// Returns a reference to the last element of the fixed array.
|
||||
reference back() { return *(end() - 1); }
|
||||
|
||||
// Overload of FixedArray::back() to return a reference to the last element
|
||||
// of a fixed array of const values.
|
||||
const_reference back() const { return *(end() - 1); }
|
||||
|
||||
// FixedArray::begin()
|
||||
//
|
||||
// Returns an iterator to the beginning of the fixed array.
|
||||
iterator begin() { return data(); }
|
||||
|
||||
// Overload of FixedArray::begin() to return a const iterator to the
|
||||
// beginning of the fixed array.
|
||||
const_iterator begin() const { return data(); }
|
||||
|
||||
// FixedArray::cbegin()
|
||||
//
|
||||
// Returns a const iterator to the beginning of the fixed array.
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
|
||||
// FixedArray::end()
|
||||
//
|
||||
// Returns an iterator to the end of the fixed array.
|
||||
iterator end() { return data() + size(); }
|
||||
|
||||
// Overload of FixedArray::end() to return a const iterator to the end of the
|
||||
// fixed array.
|
||||
const_iterator end() const { return data() + size(); }
|
||||
|
||||
// FixedArray::cend()
|
||||
//
|
||||
// Returns a const iterator to the end of the fixed array.
|
||||
const_iterator cend() const { return end(); }
|
||||
|
||||
// FixedArray::rbegin()
|
||||
//
|
||||
// Returns a reverse iterator from the end of the fixed array.
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
|
||||
// Overload of FixedArray::rbegin() to return a const reverse iterator from
|
||||
// the end of the fixed array.
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
// FixedArray::crbegin()
|
||||
//
|
||||
// Returns a const reverse iterator from the end of the fixed array.
|
||||
const_reverse_iterator crbegin() const { return rbegin(); }
|
||||
|
||||
// FixedArray::rend()
|
||||
//
|
||||
// Returns a reverse iterator from the beginning of the fixed array.
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
|
||||
// Overload of FixedArray::rend() for returning a const reverse iterator
|
||||
// from the beginning of the fixed array.
|
||||
const_reverse_iterator rend() const {
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
// FixedArray::crend()
|
||||
//
|
||||
// Returns a reverse iterator from the beginning of the fixed array.
|
||||
const_reverse_iterator crend() const { return rend(); }
|
||||
|
||||
// FixedArray::fill()
|
||||
//
|
||||
// Assigns the given `value` to all elements in the fixed array.
|
||||
void fill(const value_type& val) { std::fill(begin(), end(), val); }
|
||||
|
||||
// Relational operators. Equality operators are elementwise using
|
||||
// `operator==`, while order operators order FixedArrays lexicographically.
|
||||
friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {
|
||||
return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
friend bool operator<(const FixedArray& lhs, const FixedArray& rhs) {
|
||||
return std::lexicographical_compare(
|
||||
lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
friend bool operator>(const FixedArray& lhs, const FixedArray& rhs) {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
friend bool operator<=(const FixedArray& lhs, const FixedArray& rhs) {
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) {
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
// Container to hold elements of type T. This is necessary to handle
|
||||
// the case where T is a a (C-style) array. The size of InnerContainer
|
||||
// and T must be the same, otherwise callers' assumptions about use
|
||||
// of this code will be broken.
|
||||
struct InnerContainer {
|
||||
T element;
|
||||
// StorageElement
|
||||
//
|
||||
// For FixedArrays with a C-style-array value_type, StorageElement is a POD
|
||||
// wrapper struct called StorageElementWrapper that holds the value_type
|
||||
// instance inside. This is needed for construction and destruction of the
|
||||
// entire array regardless of how many dimensions it has. For all other cases,
|
||||
// StorageElement is just an alias of value_type.
|
||||
//
|
||||
// Maintainer's Note: The simpler solution would be to simply wrap value_type
|
||||
// in a struct whether it's an array or not. That causes some paranoid
|
||||
// diagnostics to misfire, believing that 'data()' returns a pointer to a
|
||||
// single element, rather than the packed array that it really is.
|
||||
// e.g.:
|
||||
//
|
||||
// FixedArray<char> buf(1);
|
||||
// sprintf(buf.data(), "foo");
|
||||
//
|
||||
// error: call to int __builtin___sprintf_chk(etc...)
|
||||
// will always overflow destination buffer [-Werror]
|
||||
//
|
||||
template <typename OuterT,
|
||||
typename InnerT = typename std::remove_extent<OuterT>::type,
|
||||
size_t InnerN = std::extent<OuterT>::value>
|
||||
struct StorageElementWrapper {
|
||||
InnerT array[InnerN];
|
||||
};
|
||||
|
||||
// How many elements should we store inline?
|
||||
// a. If not specified, use a default of 256 bytes (256 bytes
|
||||
// seems small enough to not cause stack overflow or unnecessary
|
||||
// stack pollution, while still allowing stack allocation for
|
||||
// reasonably long character arrays.
|
||||
// b. Never use 0 length arrays (not ISO C++)
|
||||
static const size_type S1 = ((inline_elements < 0)
|
||||
? (256/sizeof(T)) : inline_elements);
|
||||
static const size_type S2 = (S1 <= 0) ? 1 : S1;
|
||||
static const size_type kInlineElements = S2;
|
||||
using StorageElement =
|
||||
typename std::conditional<std::is_array<value_type>::value,
|
||||
StorageElementWrapper<value_type>,
|
||||
value_type>::type;
|
||||
|
||||
size_type const size_;
|
||||
InnerContainer* const array_;
|
||||
static pointer AsValueType(pointer ptr) { return ptr; }
|
||||
static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
|
||||
return std::addressof(ptr->array);
|
||||
}
|
||||
|
||||
// Allocate some space, not an array of elements of type T, so that we can
|
||||
// skip calling the T constructors and destructors for space we never use.
|
||||
ManualConstructor<InnerContainer> inline_space_[kInlineElements];
|
||||
static_assert(sizeof(StorageElement) == sizeof(value_type), "");
|
||||
static_assert(alignof(StorageElement) == alignof(value_type), "");
|
||||
|
||||
class NonEmptyInlinedStorage {
|
||||
public:
|
||||
StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
|
||||
void AnnotateConstruct(size_type) {}
|
||||
void AnnotateDestruct(size_type) {}
|
||||
|
||||
// #ifdef ADDRESS_SANITIZER
|
||||
// void* RedzoneBegin() { return &redzone_begin_; }
|
||||
// void* RedzoneEnd() { return &redzone_end_ + 1; }
|
||||
// #endif // ADDRESS_SANITIZER
|
||||
|
||||
private:
|
||||
// ADDRESS_SANITIZER_REDZONE(redzone_begin_);
|
||||
alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
|
||||
// ADDRESS_SANITIZER_REDZONE(redzone_end_);
|
||||
};
|
||||
|
||||
class EmptyInlinedStorage {
|
||||
public:
|
||||
StorageElement* data() { return nullptr; }
|
||||
void AnnotateConstruct(size_type) {}
|
||||
void AnnotateDestruct(size_type) {}
|
||||
};
|
||||
|
||||
using InlinedStorage =
|
||||
typename std::conditional<inline_elements == 0,
|
||||
EmptyInlinedStorage,
|
||||
NonEmptyInlinedStorage>::type;
|
||||
|
||||
// Storage
|
||||
//
|
||||
// An instance of Storage manages the inline and out-of-line memory for
|
||||
// instances of FixedArray. This guarantees that even when construction of
|
||||
// individual elements fails in the FixedArray constructor body, the
|
||||
// destructor for Storage will still be called and out-of-line memory will be
|
||||
// properly deallocated.
|
||||
//
|
||||
class Storage : public InlinedStorage {
|
||||
public:
|
||||
Storage(size_type n, const allocator_type& a)
|
||||
: size_alloc_(n, a), data_(InitializeData()) {}
|
||||
|
||||
~Storage() noexcept {
|
||||
if (UsingInlinedStorage(size())) {
|
||||
InlinedStorage::AnnotateDestruct(size());
|
||||
} else {
|
||||
AllocatorTraits::deallocate(alloc(), AsValueType(begin()), size());
|
||||
}
|
||||
}
|
||||
|
||||
size_type size() const { return std::get<0>(size_alloc_); }
|
||||
StorageElement* begin() const { return data_; }
|
||||
StorageElement* end() const { return begin() + size(); }
|
||||
allocator_type& alloc() { return std::get<1>(size_alloc_); }
|
||||
|
||||
private:
|
||||
static bool UsingInlinedStorage(size_type n) {
|
||||
return n <= inline_elements;
|
||||
}
|
||||
|
||||
StorageElement* InitializeData() {
|
||||
if (UsingInlinedStorage(size())) {
|
||||
InlinedStorage::AnnotateConstruct(size());
|
||||
return InlinedStorage::data();
|
||||
} else {
|
||||
return reinterpret_cast<StorageElement*>(
|
||||
AllocatorTraits::allocate(alloc(), size()));
|
||||
}
|
||||
}
|
||||
|
||||
// Using std::tuple and not absl::CompressedTuple, as it has a lot of
|
||||
// dependencies to other absl headers.
|
||||
std::tuple<size_type, allocator_type> size_alloc_;
|
||||
StorageElement* data_;
|
||||
};
|
||||
|
||||
Storage storage_;
|
||||
};
|
||||
|
||||
// Implementation details follow
|
||||
template <typename T, size_t N, typename A>
|
||||
constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
|
||||
|
||||
template <class T, ssize_t S>
|
||||
inline FixedArray<T, S>::FixedArray(typename FixedArray<T, S>::size_type n)
|
||||
: size_(n),
|
||||
array_((n <= kInlineElements
|
||||
? reinterpret_cast<InnerContainer*>(inline_space_)
|
||||
: new InnerContainer[n])) {
|
||||
// Construct only the elements actually used.
|
||||
if (array_ == reinterpret_cast<InnerContainer*>(inline_space_)) {
|
||||
for (size_t i = 0; i != size_; ++i) {
|
||||
inline_space_[i].Init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, ssize_t S>
|
||||
inline FixedArray<T, S>::~FixedArray() {
|
||||
if (array_ != reinterpret_cast<InnerContainer*>(inline_space_)) {
|
||||
delete[] array_;
|
||||
} else {
|
||||
for (size_t i = 0; i != size_; ++i) {
|
||||
inline_space_[i].Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename T, size_t N, typename A>
|
||||
constexpr typename FixedArray<T, N, A>::size_type
|
||||
FixedArray<T, N, A>::inline_elements;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
@@ -28,8 +28,8 @@
|
||||
//
|
||||
// Author: vitus@google.com (Michael Vitus)
|
||||
|
||||
#ifndef CERES_PUBLIC_HOUSEHOLDER_VECTOR_H_
|
||||
#define CERES_PUBLIC_HOUSEHOLDER_VECTOR_H_
|
||||
#ifndef CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
|
||||
#define CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
|
||||
|
||||
#include "Eigen/Core"
|
||||
#include "glog/logging.h"
|
||||
@@ -42,12 +42,15 @@ namespace internal {
|
||||
// vector as pivot instead of first. This computes the vector v with v(n) = 1
|
||||
// and beta such that H = I - beta * v * v^T is orthogonal and
|
||||
// H * x = ||x||_2 * e_n.
|
||||
template <typename Scalar>
|
||||
void ComputeHouseholderVector(const Eigen::Matrix<Scalar, Eigen::Dynamic, 1>& x,
|
||||
Eigen::Matrix<Scalar, Eigen::Dynamic, 1>* v,
|
||||
//
|
||||
// NOTE: Some versions of MSVC have trouble deducing the type of v if
|
||||
// you do not specify all the template arguments explicitly.
|
||||
template <typename XVectorType, typename Scalar, int N>
|
||||
void ComputeHouseholderVector(const XVectorType& x,
|
||||
Eigen::Matrix<Scalar, N, 1>* v,
|
||||
Scalar* beta) {
|
||||
CHECK_NOTNULL(beta);
|
||||
CHECK_NOTNULL(v);
|
||||
CHECK(beta != nullptr);
|
||||
CHECK(v != nullptr);
|
||||
CHECK_GT(x.rows(), 1);
|
||||
CHECK_EQ(x.rows(), v->rows());
|
||||
|
||||
@@ -82,4 +85,4 @@ void ComputeHouseholderVector(const Eigen::Matrix<Scalar, Eigen::Dynamic, 1>& x,
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_HOUSEHOLDER_VECTOR_H_
|
||||
#endif // CERES_PUBLIC_INTERNAL_HOUSEHOLDER_VECTOR_H_
|
165
extern/ceres/include/ceres/internal/integer_sequence_algorithm.h
vendored
Normal file
165
extern/ceres/include/ceres/internal/integer_sequence_algorithm.h
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: jodebo_beck@gmx.de (Johannes Beck)
|
||||
//
|
||||
// Algorithms to be used together with integer_sequence, like computing the sum
|
||||
// or the exclusive scan (sometimes called exclusive prefix sum) at compile
|
||||
// time.
|
||||
|
||||
#ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|
||||
#define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// Implementation of calculating the sum of an integer sequence.
|
||||
// Recursively instantiate SumImpl and calculate the sum of the N first
|
||||
// numbers. This reduces the number of instantiations and speeds up
|
||||
// compilation.
|
||||
//
|
||||
// Examples:
|
||||
// 1) integer_sequence<int, 5>:
|
||||
// Value = 5
|
||||
//
|
||||
// 2) integer_sequence<int, 4, 2>:
|
||||
// Value = 4 + 2 + SumImpl<integer_sequence<int>>::Value
|
||||
// Value = 4 + 2 + 0
|
||||
//
|
||||
// 3) integer_sequence<int, 2, 1, 4>:
|
||||
// Value = 2 + 1 + SumImpl<integer_sequence<int, 4>>::Value
|
||||
// Value = 2 + 1 + 4
|
||||
template <typename Seq>
|
||||
struct SumImpl;
|
||||
|
||||
// Strip of and sum the first number.
|
||||
template <typename T, T N, T... Ns>
|
||||
struct SumImpl<std::integer_sequence<T, N, Ns...>> {
|
||||
static constexpr T Value = N + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
||||
};
|
||||
|
||||
// Strip of and sum the first two numbers.
|
||||
template <typename T, T N1, T N2, T... Ns>
|
||||
struct SumImpl<std::integer_sequence<T, N1, N2, Ns...>> {
|
||||
static constexpr T Value =
|
||||
N1 + N2 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
||||
};
|
||||
|
||||
// Strip of and sum the first four numbers.
|
||||
template <typename T, T N1, T N2, T N3, T N4, T... Ns>
|
||||
struct SumImpl<std::integer_sequence<T, N1, N2, N3, N4, Ns...>> {
|
||||
static constexpr T Value =
|
||||
N1 + N2 + N3 + N4 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
||||
};
|
||||
|
||||
// Only one number is left. 'Value' is just that number ('recursion' ends).
|
||||
template <typename T, T N>
|
||||
struct SumImpl<std::integer_sequence<T, N>> {
|
||||
static constexpr T Value = N;
|
||||
};
|
||||
|
||||
// No number is left. 'Value' is the identity element (for sum this is zero).
|
||||
template <typename T>
|
||||
struct SumImpl<std::integer_sequence<T>> {
|
||||
static constexpr T Value = T(0);
|
||||
};
|
||||
|
||||
// Calculate the sum of an integer sequence. The resulting sum will be stored in
|
||||
// 'Value'.
|
||||
template <typename Seq>
|
||||
class Sum {
|
||||
using T = typename Seq::value_type;
|
||||
|
||||
public:
|
||||
static constexpr T Value = SumImpl<Seq>::Value;
|
||||
};
|
||||
|
||||
// Implementation of calculating an exclusive scan (exclusive prefix sum) of an
|
||||
// integer sequence. Exclusive means that the i-th input element is not included
|
||||
// in the i-th sum. Calculating the exclusive scan for an input array I results
|
||||
// in the following output R:
|
||||
//
|
||||
// R[0] = 0
|
||||
// R[1] = I[0];
|
||||
// R[2] = I[0] + I[1];
|
||||
// R[3] = I[0] + I[1] + I[2];
|
||||
// ...
|
||||
//
|
||||
// In C++17 std::exclusive_scan does the same operation at runtime (but
|
||||
// cannot be used to calculate the prefix sum at compile time). See
|
||||
// https://en.cppreference.com/w/cpp/algorithm/exclusive_scan for a more
|
||||
// detailed description.
|
||||
//
|
||||
// Example for integer_sequence<int, 1, 4, 3> (seq := integer_sequence):
|
||||
// T , Sum, Ns... , Rs...
|
||||
// ExclusiveScanImpl<int, 0, seq<int, 1, 4, 3>, seq<int >>
|
||||
// ExclusiveScanImpl<int, 1, seq<int, 4, 3>, seq<int, 0 >>
|
||||
// ExclusiveScanImpl<int, 5, seq<int, 3>, seq<int, 0, 1 >>
|
||||
// ExclusiveScanImpl<int, 8, seq<int >, seq<int, 0, 1, 5>>
|
||||
// ^^^^^^^^^^^^^^^^^
|
||||
// resulting sequence
|
||||
template <typename T, T Sum, typename SeqIn, typename SeqOut>
|
||||
struct ExclusiveScanImpl;
|
||||
|
||||
template <typename T, T Sum, T N, T... Ns, T... Rs>
|
||||
struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T, N, Ns...>,
|
||||
std::integer_sequence<T, Rs...>> {
|
||||
using Type =
|
||||
typename ExclusiveScanImpl<T, Sum + N, std::integer_sequence<T, Ns...>,
|
||||
std::integer_sequence<T, Rs..., Sum>>::Type;
|
||||
};
|
||||
|
||||
// End of 'recursion'. The resulting type is SeqOut.
|
||||
template <typename T, T Sum, typename SeqOut>
|
||||
struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T>, SeqOut> {
|
||||
using Type = SeqOut;
|
||||
};
|
||||
|
||||
// Calculates the exclusive scan of the specified integer sequence. The last
|
||||
// element (the total) is not included in the resulting sequence so they have
|
||||
// same length. This means the exclusive scan of integer_sequence<int, 1, 2, 3>
|
||||
// will be integer_sequence<int, 0, 1, 3>.
|
||||
template <typename Seq>
|
||||
class ExclusiveScanT {
|
||||
using T = typename Seq::value_type;
|
||||
|
||||
public:
|
||||
using Type =
|
||||
typename ExclusiveScanImpl<T, T(0), Seq, std::integer_sequence<T>>::Type;
|
||||
};
|
||||
|
||||
// Helper to use exclusive scan without typename.
|
||||
template <typename Seq>
|
||||
using ExclusiveScan = typename ExclusiveScanT<Seq>::Type;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|
183
extern/ceres/include/ceres/internal/line_parameterization.h
vendored
Normal file
183
extern/ceres/include/ceres/internal/line_parameterization.h
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2020 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: jodebo_beck@gmx.de (Johannes Beck)
|
||||
//
|
||||
|
||||
#ifndef CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
|
||||
#define CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
|
||||
|
||||
#include "householder_vector.h"
|
||||
|
||||
namespace ceres {
|
||||
|
||||
template <int AmbientSpaceDimension>
|
||||
bool LineParameterization<AmbientSpaceDimension>::Plus(
|
||||
const double* x_ptr,
|
||||
const double* delta_ptr,
|
||||
double* x_plus_delta_ptr) const {
|
||||
// We seek a box plus operator of the form
|
||||
//
|
||||
// [o*, d*] = Plus([o, d], [delta_o, delta_d])
|
||||
//
|
||||
// where o is the origin point, d is the direction vector, delta_o is
|
||||
// the delta of the origin point and delta_d the delta of the direction and
|
||||
// o* and d* is the updated origin point and direction.
|
||||
//
|
||||
// We separate the Plus operator into the origin point and directional part
|
||||
// d* = Plus_d(d, delta_d)
|
||||
// o* = Plus_o(o, d, delta_o)
|
||||
//
|
||||
// The direction update function Plus_d is the same as for the homogeneous
|
||||
// vector parameterization:
|
||||
//
|
||||
// d* = H_{v(d)} [0.5 sinc(0.5 |delta_d|) delta_d, cos(0.5 |delta_d|)]^T
|
||||
//
|
||||
// where H is the householder matrix
|
||||
// H_{v} = I - (2 / |v|^2) v v^T
|
||||
// and
|
||||
// v(d) = d - sign(d_n) |d| e_n.
|
||||
//
|
||||
// The origin point update function Plus_o is defined as
|
||||
//
|
||||
// o* = o + H_{v(d)} [0.5 delta_o, 0]^T.
|
||||
|
||||
static constexpr int kDim = AmbientSpaceDimension;
|
||||
using AmbientVector = Eigen::Matrix<double, kDim, 1>;
|
||||
using AmbientVectorRef = Eigen::Map<Eigen::Matrix<double, kDim, 1>>;
|
||||
using ConstAmbientVectorRef =
|
||||
Eigen::Map<const Eigen::Matrix<double, kDim, 1>>;
|
||||
using ConstTangentVectorRef =
|
||||
Eigen::Map<const Eigen::Matrix<double, kDim - 1, 1>>;
|
||||
|
||||
ConstAmbientVectorRef o(x_ptr);
|
||||
ConstAmbientVectorRef d(x_ptr + kDim);
|
||||
|
||||
ConstTangentVectorRef delta_o(delta_ptr);
|
||||
ConstTangentVectorRef delta_d(delta_ptr + kDim - 1);
|
||||
AmbientVectorRef o_plus_delta(x_plus_delta_ptr);
|
||||
AmbientVectorRef d_plus_delta(x_plus_delta_ptr + kDim);
|
||||
|
||||
const double norm_delta_d = delta_d.norm();
|
||||
|
||||
o_plus_delta = o;
|
||||
|
||||
// Shortcut for zero delta direction.
|
||||
if (norm_delta_d == 0.0) {
|
||||
d_plus_delta = d;
|
||||
|
||||
if (delta_o.isZero(0.0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the householder transformation which is needed for f_d and f_o.
|
||||
AmbientVector v;
|
||||
double beta;
|
||||
|
||||
// NOTE: The explicit template arguments are needed here because
|
||||
// ComputeHouseholderVector is templated and some versions of MSVC
|
||||
// have trouble deducing the type of v automatically.
|
||||
internal::ComputeHouseholderVector<ConstAmbientVectorRef, double, kDim>(
|
||||
d, &v, &beta);
|
||||
|
||||
if (norm_delta_d != 0.0) {
|
||||
// Map the delta from the minimum representation to the over parameterized
|
||||
// homogeneous vector. See section A6.9.2 on page 624 of Hartley & Zisserman
|
||||
// (2nd Edition) for a detailed description. Note there is a typo on Page
|
||||
// 625, line 4 so check the book errata.
|
||||
const double norm_delta_div_2 = 0.5 * norm_delta_d;
|
||||
const double sin_delta_by_delta =
|
||||
std::sin(norm_delta_div_2) / norm_delta_div_2;
|
||||
|
||||
// Apply the delta update to remain on the unit sphere. See section A6.9.3
|
||||
// on page 625 of Hartley & Zisserman (2nd Edition) for a detailed
|
||||
// description.
|
||||
AmbientVector y;
|
||||
y.template head<kDim - 1>() = 0.5 * sin_delta_by_delta * delta_d;
|
||||
y[kDim - 1] = std::cos(norm_delta_div_2);
|
||||
|
||||
d_plus_delta = d.norm() * (y - v * (beta * (v.transpose() * y)));
|
||||
}
|
||||
|
||||
// The null space is in the direction of the line, so the tangent space is
|
||||
// perpendicular to the line direction. This is achieved by using the
|
||||
// householder matrix of the direction and allow only movements
|
||||
// perpendicular to e_n.
|
||||
//
|
||||
// The factor of 0.5 is used to be consistent with the line direction
|
||||
// update.
|
||||
AmbientVector y;
|
||||
y << 0.5 * delta_o, 0;
|
||||
o_plus_delta += y - v * (beta * (v.transpose() * y));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int AmbientSpaceDimension>
|
||||
bool LineParameterization<AmbientSpaceDimension>::ComputeJacobian(
|
||||
const double* x_ptr, double* jacobian_ptr) const {
|
||||
static constexpr int kDim = AmbientSpaceDimension;
|
||||
using AmbientVector = Eigen::Matrix<double, kDim, 1>;
|
||||
using ConstAmbientVectorRef =
|
||||
Eigen::Map<const Eigen::Matrix<double, kDim, 1>>;
|
||||
using MatrixRef = Eigen::Map<
|
||||
Eigen::Matrix<double, 2 * kDim, 2 * (kDim - 1), Eigen::RowMajor>>;
|
||||
|
||||
ConstAmbientVectorRef d(x_ptr + kDim);
|
||||
MatrixRef jacobian(jacobian_ptr);
|
||||
|
||||
// Clear the Jacobian as only half of the matrix is not zero.
|
||||
jacobian.setZero();
|
||||
|
||||
AmbientVector v;
|
||||
double beta;
|
||||
|
||||
// NOTE: The explicit template arguments are needed here because
|
||||
// ComputeHouseholderVector is templated and some versions of MSVC
|
||||
// have trouble deducing the type of v automatically.
|
||||
internal::ComputeHouseholderVector<ConstAmbientVectorRef, double, kDim>(
|
||||
d, &v, &beta);
|
||||
|
||||
// The Jacobian is equal to J = 0.5 * H.leftCols(kDim - 1) where H is
|
||||
// the Householder matrix (H = I - beta * v * v') for the origin point. For
|
||||
// the line direction part the Jacobian is scaled by the norm of the
|
||||
// direction.
|
||||
for (int i = 0; i < kDim - 1; ++i) {
|
||||
jacobian.block(0, i, kDim, 1) = -0.5 * beta * v(i) * v;
|
||||
jacobian.col(i)(i) += 0.5;
|
||||
}
|
||||
|
||||
jacobian.template block<kDim, kDim - 1>(kDim, kDim - 1) =
|
||||
jacobian.template block<kDim, kDim - 1>(0, 0) * d.norm();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_INTERNAL_LINE_PARAMETERIZATION_H_
|
170
extern/ceres/include/ceres/internal/macros.h
vendored
170
extern/ceres/include/ceres/internal/macros.h
vendored
@@ -1,170 +0,0 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//
|
||||
// Various Google-specific macros.
|
||||
//
|
||||
// This code is compiled directly on many platforms, including client
|
||||
// platforms like Windows, Mac, and embedded systems. Before making
|
||||
// any changes here, make sure that you're not breaking any platforms.
|
||||
|
||||
#ifndef CERES_PUBLIC_INTERNAL_MACROS_H_
|
||||
#define CERES_PUBLIC_INTERNAL_MACROS_H_
|
||||
|
||||
#include <cstddef> // For size_t.
|
||||
|
||||
// A macro to disallow the copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
//
|
||||
// For disallowing only assign or copy, write the code directly, but declare
|
||||
// the intend in a comment, for example:
|
||||
//
|
||||
// void operator=(const TypeName&); // _DISALLOW_ASSIGN
|
||||
|
||||
// Note, that most uses of CERES_DISALLOW_ASSIGN and CERES_DISALLOW_COPY
|
||||
// are broken semantically, one should either use disallow both or
|
||||
// neither. Try to avoid these in new code.
|
||||
#define CERES_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
// A macro to disallow all the implicit constructors, namely the
|
||||
// default constructor, copy constructor and operator= functions.
|
||||
//
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#define CERES_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
CERES_DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
|
||||
// The arraysize(arr) macro returns the # of elements in an array arr.
|
||||
// The expression is a compile-time constant, and therefore can be
|
||||
// used in defining new arrays, for example. If you use arraysize on
|
||||
// a pointer by mistake, you will get a compile-time error.
|
||||
//
|
||||
// One caveat is that arraysize() doesn't accept any array of an
|
||||
// anonymous type or a type defined inside a function. In these rare
|
||||
// cases, you have to use the unsafe ARRAYSIZE() macro below. This is
|
||||
// due to a limitation in C++'s template system. The limitation might
|
||||
// eventually be removed, but it hasn't happened yet.
|
||||
|
||||
// This template function declaration is used in defining arraysize.
|
||||
// Note that the function doesn't need an implementation, as we only
|
||||
// use its type.
|
||||
template <typename T, size_t N>
|
||||
char (&ArraySizeHelper(T (&array)[N]))[N];
|
||||
|
||||
// That gcc wants both of these prototypes seems mysterious. VC, for
|
||||
// its part, can't decide which to use (another mystery). Matching of
|
||||
// template overloads: the final frontier.
|
||||
#ifndef _WIN32
|
||||
template <typename T, size_t N>
|
||||
char (&ArraySizeHelper(const T (&array)[N]))[N];
|
||||
#endif
|
||||
|
||||
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
||||
|
||||
// ARRAYSIZE performs essentially the same calculation as arraysize,
|
||||
// but can be used on anonymous types or types defined inside
|
||||
// functions. It's less safe than arraysize as it accepts some
|
||||
// (although not all) pointers. Therefore, you should use arraysize
|
||||
// whenever possible.
|
||||
//
|
||||
// The expression ARRAYSIZE(a) is a compile-time constant of type
|
||||
// size_t.
|
||||
//
|
||||
// ARRAYSIZE catches a few type errors. If you see a compiler error
|
||||
//
|
||||
// "warning: division by zero in ..."
|
||||
//
|
||||
// when using ARRAYSIZE, you are (wrongfully) giving it a pointer.
|
||||
// You should only use ARRAYSIZE on statically allocated arrays.
|
||||
//
|
||||
// The following comments are on the implementation details, and can
|
||||
// be ignored by the users.
|
||||
//
|
||||
// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
|
||||
// the array) and sizeof(*(arr)) (the # of bytes in one array
|
||||
// element). If the former is divisible by the latter, perhaps arr is
|
||||
// indeed an array, in which case the division result is the # of
|
||||
// elements in the array. Otherwise, arr cannot possibly be an array,
|
||||
// and we generate a compiler error to prevent the code from
|
||||
// compiling.
|
||||
//
|
||||
// Since the size of bool is implementation-defined, we need to cast
|
||||
// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
|
||||
// result has type size_t.
|
||||
//
|
||||
// This macro is not perfect as it wrongfully accepts certain
|
||||
// pointers, namely where the pointer size is divisible by the pointee
|
||||
// size. Since all our code has to go through a 32-bit compiler,
|
||||
// where a pointer is 4 bytes, this means all pointers to a type whose
|
||||
// size is 3 or greater than 4 will be (righteously) rejected.
|
||||
//
|
||||
// Kudos to Jorg Brown for this simple and elegant implementation.
|
||||
//
|
||||
// - wan 2005-11-16
|
||||
//
|
||||
// Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE. However,
|
||||
// the definition comes from the over-broad windows.h header that
|
||||
// introduces a macro, ERROR, that conflicts with the logging framework
|
||||
// that Ceres uses. Instead, rename ARRAYSIZE to CERES_ARRAYSIZE.
|
||||
#define CERES_ARRAYSIZE(a) \
|
||||
((sizeof(a) / sizeof(*(a))) / \
|
||||
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
||||
|
||||
// Tell the compiler to warn about unused return values for functions
|
||||
// declared with this macro. The macro should be used on function
|
||||
// declarations following the argument list:
|
||||
//
|
||||
// Sprocket* AllocateSprocket() MUST_USE_RESULT;
|
||||
//
|
||||
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
|
||||
&& !defined(COMPILER_ICC)
|
||||
#define CERES_MUST_USE_RESULT __attribute__ ((warn_unused_result))
|
||||
#else
|
||||
#define CERES_MUST_USE_RESULT
|
||||
#endif
|
||||
|
||||
// Platform independent macros to get aligned memory allocations.
|
||||
// For example
|
||||
//
|
||||
// MyFoo my_foo CERES_ALIGN_ATTRIBUTE(16);
|
||||
//
|
||||
// Gives us an instance of MyFoo which is aligned at a 16 byte
|
||||
// boundary.
|
||||
#if defined(_MSC_VER)
|
||||
#define CERES_ALIGN_ATTRIBUTE(n) __declspec(align(n))
|
||||
#define CERES_ALIGN_OF(T) __alignof(T)
|
||||
#elif defined(__GNUC__)
|
||||
#define CERES_ALIGN_ATTRIBUTE(n) __attribute__((aligned(n)))
|
||||
#define CERES_ALIGN_OF(T) __alignof(T)
|
||||
#endif
|
||||
|
||||
#endif // CERES_PUBLIC_INTERNAL_MACROS_H_
|
@@ -1,208 +0,0 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
//
|
||||
// ManualConstructor statically-allocates space in which to store some
|
||||
// object, but does not initialize it. You can then call the constructor
|
||||
// and destructor for the object yourself as you see fit. This is useful
|
||||
// for memory management optimizations, where you want to initialize and
|
||||
// destroy an object multiple times but only allocate it once.
|
||||
//
|
||||
// (When I say ManualConstructor statically allocates space, I mean that
|
||||
// the ManualConstructor object itself is forced to be the right size.)
|
||||
|
||||
#ifndef CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
|
||||
#define CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
|
||||
|
||||
#include <new>
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// ------- Define CERES_ALIGNED_CHAR_ARRAY --------------------------------
|
||||
|
||||
#ifndef CERES_ALIGNED_CHAR_ARRAY
|
||||
|
||||
// Because MSVC and older GCCs require that the argument to their alignment
|
||||
// construct to be a literal constant integer, we use a template instantiated
|
||||
// at all the possible powers of two.
|
||||
template<int alignment, int size> struct AlignType { };
|
||||
template<int size> struct AlignType<0, size> { typedef char result[size]; };
|
||||
|
||||
#if !defined(CERES_ALIGN_ATTRIBUTE)
|
||||
#define CERES_ALIGNED_CHAR_ARRAY you_must_define_CERES_ALIGNED_CHAR_ARRAY_for_your_compiler
|
||||
#else // !defined(CERES_ALIGN_ATTRIBUTE)
|
||||
|
||||
#define CERES_ALIGN_TYPE_TEMPLATE(X) \
|
||||
template<int size> struct AlignType<X, size> { \
|
||||
typedef CERES_ALIGN_ATTRIBUTE(X) char result[size]; \
|
||||
}
|
||||
|
||||
CERES_ALIGN_TYPE_TEMPLATE(1);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(2);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(4);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(8);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(16);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(32);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(64);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(128);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(256);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(512);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(1024);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(2048);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(4096);
|
||||
CERES_ALIGN_TYPE_TEMPLATE(8192);
|
||||
// Any larger and MSVC++ will complain.
|
||||
|
||||
#undef CERES_ALIGN_TYPE_TEMPLATE
|
||||
|
||||
#define CERES_ALIGNED_CHAR_ARRAY(T, Size) \
|
||||
typename AlignType<CERES_ALIGN_OF(T), sizeof(T) * Size>::result
|
||||
|
||||
#endif // !defined(CERES_ALIGN_ATTRIBUTE)
|
||||
|
||||
#endif // CERES_ALIGNED_CHAR_ARRAY
|
||||
|
||||
template <typename Type>
|
||||
class ManualConstructor {
|
||||
public:
|
||||
// No constructor or destructor because one of the most useful uses of
|
||||
// this class is as part of a union, and members of a union cannot have
|
||||
// constructors or destructors. And, anyway, the whole point of this
|
||||
// class is to bypass these.
|
||||
|
||||
inline Type* get() {
|
||||
return reinterpret_cast<Type*>(space_);
|
||||
}
|
||||
inline const Type* get() const {
|
||||
return reinterpret_cast<const Type*>(space_);
|
||||
}
|
||||
|
||||
inline Type* operator->() { return get(); }
|
||||
inline const Type* operator->() const { return get(); }
|
||||
|
||||
inline Type& operator*() { return *get(); }
|
||||
inline const Type& operator*() const { return *get(); }
|
||||
|
||||
// This is needed to get around the strict aliasing warning GCC generates.
|
||||
inline void* space() {
|
||||
return reinterpret_cast<void*>(space_);
|
||||
}
|
||||
|
||||
// You can pass up to four constructor arguments as arguments of Init().
|
||||
inline void Init() {
|
||||
new(space()) Type;
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
inline void Init(const T1& p1) {
|
||||
new(space()) Type(p1);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void Init(const T1& p1, const T2& p2) {
|
||||
new(space()) Type(p1, p2);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
inline void Init(const T1& p1, const T2& p2, const T3& p3) {
|
||||
new(space()) Type(p1, p2, p3);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) {
|
||||
new(space()) Type(p1, p2, p3, p4);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||
const T5& p5) {
|
||||
new(space()) Type(p1, p2, p3, p4, p5);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6>
|
||||
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||
const T5& p5, const T6& p6) {
|
||||
new(space()) Type(p1, p2, p3, p4, p5, p6);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7>
|
||||
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||
const T5& p5, const T6& p6, const T7& p7) {
|
||||
new(space()) Type(p1, p2, p3, p4, p5, p6, p7);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8>
|
||||
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||
const T5& p5, const T6& p6, const T7& p7, const T8& p8) {
|
||||
new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8, typename T9>
|
||||
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
|
||||
const T9& p9) {
|
||||
new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8, typename T9, typename T10>
|
||||
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
|
||||
const T9& p9, const T10& p10) {
|
||||
new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8, typename T9, typename T10,
|
||||
typename T11>
|
||||
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
|
||||
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
|
||||
const T9& p9, const T10& p10, const T11& p11) {
|
||||
new(space()) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
|
||||
}
|
||||
|
||||
inline void Destroy() {
|
||||
get()->~Type();
|
||||
}
|
||||
|
||||
private:
|
||||
CERES_ALIGNED_CHAR_ARRAY(Type, 1) space_;
|
||||
};
|
||||
|
||||
#undef CERES_ALIGNED_CHAR_ARRAY
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user