Compare commits
632 Commits
functions
...
blenloader
Author | SHA1 | Date | |
---|---|---|---|
f4937677d9 | |||
da09867c9f | |||
090947ce6c | |||
9bde79d734 | |||
64cdcf7973 | |||
ef817015d1 | |||
2b7d5caae8 | |||
1a6119c8e4 | |||
6a0cb48149 | |||
a6380d063f | |||
ccaab72685 | |||
![]() |
5366eb89c6 | ||
0d65520f05 | |||
d388c1c524 | |||
76be35efb2 | |||
b64fdbfb98 | |||
5240df4e0c | |||
6408cd00c5 | |||
7df51ca11a | |||
5ef94c9c41 | |||
1623fdb3bc | |||
719cff1414 | |||
cfdff4fb63 | |||
03b911dd87 | |||
e590199949 | |||
92d62148be | |||
c06a40006d | |||
83304e4c22 | |||
7212dbd7be | |||
bba11c68c4 | |||
447a7f510e | |||
433eaffd55 | |||
805a78e396 | |||
06839379c5 | |||
![]() |
51aa0ea58f | ||
87602d886f | |||
![]() |
98990f6ba4 | ||
b52b5e15af | |||
9ca78c9bcc | |||
eddddceb8e | |||
716638458d | |||
57d1db27c7 | |||
5b6ee80351 | |||
9c2c697011 | |||
b22abd112d | |||
60741cfe18 | |||
b83a8d6fc4 | |||
f651548c2e | |||
75370684fa | |||
b523911e86 | |||
4cc8123377 | |||
2188175891 | |||
d49b148459 | |||
185e1d5395 | |||
ae049a6c6a | |||
aa72e3abf9 | |||
28bdf669a9 | |||
d7d140ec7f | |||
9a4844cfdb | |||
d1c0d77e18 | |||
![]() |
b2d850efc0 | ||
e28d2e5184 | |||
7ded7610ce | |||
47fea20dc8 | |||
d602af73d3 | |||
aff5e18adb | |||
ff1174e52c | |||
a6fbd4c9c8 | |||
b7117b5728 | |||
f7d98d3582 | |||
635754a876 | |||
5ee1c7f695 | |||
0cb53d4740 | |||
7a809a7504 | |||
4d790516fb | |||
03f4d20bcf | |||
![]() |
99cb6dbe65 | ||
1d63db2044 | |||
1960b8a361 | |||
713ad9d971 | |||
d8abef6d7c | |||
f90a716e68 | |||
![]() |
8e08d80e52 | ||
d44f323df5 | |||
38456d3e82 | |||
31d3f034ab | |||
4612ca3ede | |||
150950e30f | |||
f4b020eec3 | |||
f5237f7704 | |||
0316676e71 | |||
21485e94aa | |||
c4a850b7c2 | |||
e7e6b02ed9 | |||
713b4c10a6 | |||
134619fabb | |||
f28875a998 | |||
d4c547b7bd | |||
6a7e9f2b76 | |||
dc0a564c06 | |||
9ee7fc15af | |||
4d63dfca4c | |||
6121c28501 | |||
7163e159c5 | |||
ea77584d36 | |||
41b45d9159 | |||
ae98a033c8 | |||
79269e4237 | |||
36bf067ddc | |||
7f4c4011ce | |||
328da12598 | |||
2b094be949 | |||
02c77e4e5c | |||
070bf01d37 | |||
52186a39af | |||
e1d4c3bc36 | |||
040e98dfc9 | |||
d8a3f3595a | |||
a18ad3c3b6 | |||
66e70fe299 | |||
00e0034b13 | |||
cd833d8879 | |||
d07dab0d61 | |||
a54c1f1e77 | |||
7f5367eaae | |||
080732ae5c | |||
b7bcd0a87c | |||
0ddf5860f5 | |||
6c4ef6159c | |||
0cfd2d6f4b | |||
c57e4418bb | |||
980cebc459 | |||
157f836493 | |||
2845b232a7 | |||
657188c1a2 | |||
08048f7cce | |||
fed5e0ca04 | |||
e07b245fe1 | |||
cedf9f5cb7 | |||
9a9ecad65f | |||
afeddd42e6 | |||
3af52c6ec3 | |||
839fe335d2 | |||
1e58255c40 | |||
![]() |
b3ac6d1348 | ||
770605312f | |||
601a1a3fda | |||
21ef8c4d44 | |||
af835ee6f8 | |||
3ea67e08fe | |||
cec9dbc997 | |||
05274ca829 | |||
d66aa52528 | |||
b443e1b7d4 | |||
4d06c1c25b | |||
44ac789a3a | |||
cdd980cd56 | |||
d366658d2d | |||
c1e6865ee3 | |||
67bd6bbcdd | |||
05283f8c96 | |||
7dfa1b18c1 | |||
7bc4a436a0 | |||
475bd6b829 | |||
a72eed7dd5 | |||
c05ef1459c | |||
d575b72c16 | |||
69e8de434f | |||
6278b48ea1 | |||
37e08e526c | |||
9f090bac5c | |||
1c7317a6da | |||
9c65ac7311 | |||
7d85b6431f | |||
2c60221080 | |||
20100009f6 | |||
7d1bb2edfd | |||
8da80e7771 | |||
2db4a5bb9f | |||
2580fa1602 | |||
6cab53eaaa | |||
b21a3e7702 | |||
a7bd835644 | |||
![]() |
b9f422c4be | ||
18e9626e41 | |||
4adc68bdf8 | |||
9c2715ffda | |||
7acc8a5a92 | |||
0372121e17 | |||
a66162e1f6 | |||
3afa2e94ba | |||
90f01d5048 | |||
c7144d780d | |||
64e242244d | |||
4f639b893b | |||
612757b524 | |||
a8d684d87f | |||
ef1187387b | |||
e78470d954 | |||
33017e9529 | |||
fd0cb58122 | |||
133bf05b18 | |||
84e40ee846 | |||
6830307b94 | |||
ad01bab6c3 | |||
15081cf6df | |||
7951ec2641 | |||
ea75701529 | |||
a1b1f2acd4 | |||
94c514cf34 | |||
![]() |
af876b12f1 | ||
5f3990d69a | |||
fbae4c5ba3 | |||
0a7dd1ec49 | |||
a4df7f78a8 | |||
61f0941321 | |||
b0f207db15 | |||
5559edf3c7 | |||
995611640e | |||
4119e9c60b | |||
4fd005fefb | |||
6842958c9b | |||
b6592c83b5 | |||
8f289196cf | |||
7c782b8f27 | |||
536055e1ee | |||
3d7ac7feba | |||
b1037aa88f | |||
3c858246cd | |||
f346fd3212 | |||
7300e8a9fe | |||
fc1ea38c63 | |||
![]() |
bb1e794d58 | ||
![]() |
0da05720de | ||
![]() |
54eb701978 | ||
490c32c425 | |||
13abd3784a | |||
d0d16eb7d3 | |||
![]() |
8a94903c09 | ||
0edf3f5680 | |||
c13ad410a6 | |||
576ecbd694 | |||
dea1c1b9eb | |||
a2de3d86de | |||
066b0248df | |||
05b94c9c54 | |||
8d8414cd21 | |||
f418eddf8e | |||
e54a206e15 | |||
78887318e2 | |||
53106934f9 | |||
2b95f2439e | |||
4ab85a3380 | |||
5d14463e1a | |||
c5f4d5e448 | |||
1f2b1d520f | |||
ebe0d7ca5e | |||
62f6255b47 | |||
fd10ac9aca | |||
a8441fc900 | |||
be5c9d45bd | |||
be00902082 | |||
246d59ff0f | |||
47ae0affc8 | |||
69b6c89842 | |||
ed32afd962 | |||
4542b50afc | |||
0de591ac39 | |||
1625b7c37c | |||
c2bf0c1d54 | |||
e8d3996e67 | |||
b0b6fb8a93 | |||
a8e89db291 | |||
9b56b2b2b9 | |||
d4ffd1d91f | |||
c1e4b369b0 | |||
001629a362 | |||
d2aa4ada50 | |||
d428cca124 | |||
9667f89e82 | |||
af0a042da7 | |||
826f6dd9ee | |||
d712f1f83a | |||
d0ff3434cf | |||
54e1b63567 | |||
ed4f33a7bd | |||
8f5a4a4da3 | |||
7d98dfd6bb | |||
0fbcb824d0 | |||
c03b6f6f0b | |||
40f2c92460 | |||
2467f4df79 | |||
53de2c3e4f | |||
5e04548500 | |||
869472b3f0 | |||
3b47f335c6 | |||
1fce2ea743 | |||
694c0547c2 | |||
6524aaf685 | |||
5afba30c69 | |||
1c84cd8198 | |||
a0652430d0 | |||
35ecfefaec | |||
8f51f60948 | |||
3a0af215b9 | |||
614621747e | |||
68cfce1519 | |||
8dedbb1747 | |||
6c0ddf1110 | |||
b900a5e452 | |||
6489f5a8ec | |||
83d9ba341e | |||
b785feb3d7 | |||
e812512e1d | |||
5491c045af | |||
101ec2f3b8 | |||
c3accabef9 | |||
c632396733 | |||
f6f4ab3ebf | |||
a68bd94d11 | |||
f7753bf97f | |||
6f8d5eaa28 | |||
d17b371a83 | |||
c3d8fa1301 | |||
821316b034 | |||
22cf2572d9 | |||
0dfe30502a | |||
f9649e2bf1 | |||
f5b540593c | |||
de168b4115 | |||
878cd0e124 | |||
cdc399a055 | |||
45f8d1783b | |||
cf5147f69f | |||
138b0c970e | |||
0fe3e38b57 | |||
07ed64aae6 | |||
f148bd3795 | |||
6485d8b78a | |||
fdea3dd7e7 | |||
d19277c72f | |||
650f9cfe93 | |||
abdd4117b1 | |||
40e9dc638b | |||
06e3df4ce4 | |||
5cae44ef6d | |||
912ac457a6 | |||
9000ec3013 | |||
6a1056c6a8 | |||
28f7c80c46 | |||
6c9bebd827 | |||
a0fe22095e | |||
8d5ae15040 | |||
a47a975a55 | |||
6c9a882340 | |||
e5052e8bde | |||
9aeb475e99 | |||
c69a047b90 | |||
![]() |
aa09a46fd7 | ||
dfe22c2900 | |||
470f17f21c | |||
bc83fc9c04 | |||
b2cc2dda9c | |||
aba78caa11 | |||
8eeae02cb0 | |||
c7991bcefc | |||
3542c5eb72 | |||
21f811cb6d | |||
1998154ff4 | |||
0faeca806c | |||
f7374737ef | |||
13e3a1c532 | |||
8845b27dce | |||
bc3aab3fa5 | |||
93e193399d | |||
38f4b95635 | |||
29e9506a7f | |||
3059353b38 | |||
0e52b91f97 | |||
805c52b1fd | |||
b08e18ff36 | |||
2d6ad88466 | |||
23919d2275 | |||
6505dd1985 | |||
ec14bee20d | |||
2de0cc5adc | |||
b4993a9032 | |||
f4ee9643ad | |||
![]() |
ad23b1e91d | ||
a93ed3bcb7 | |||
9528fa2c46 | |||
6f598ecc1a | |||
81d29a9f61 | |||
5fed9ac9b5 | |||
1c86912068 | |||
06a2ae281b | |||
c73d6162be | |||
49a29c9c76 | |||
a02da85b55 | |||
55a2682348 | |||
9618bd9202 | |||
be7c51d076 | |||
749181ff4d | |||
e9c9e1c2c7 | |||
f0e8965090 | |||
ce82e9e64a | |||
c334020d8f | |||
838d452843 | |||
584f112548 | |||
3135791395 | |||
![]() |
7865185d98 | ||
665bf41f3c | |||
d1da2f0b9e | |||
7ff0f896e8 | |||
8dbbac43bb | |||
dcb45992bf | |||
aa2544793d | |||
b78f2675d7 | |||
915866f0d9 | |||
9f7bea6e83 | |||
e7acf17b74 | |||
8759813abd | |||
2b2d3c14fe | |||
8d53e59e32 | |||
1b01d10998 | |||
67593a41dd | |||
25e774422c | |||
bc71074d0a | |||
0247ee5f53 | |||
eb4e3bbe68 | |||
5f5ec7b0ed | |||
005bba2a81 | |||
0e7871f9c3 | |||
0e6c56760c | |||
2a96e8be39 | |||
9d3b1d361d | |||
23bb42a06e | |||
b293517d7b | |||
30bfa991f8 | |||
9776b8a05e | |||
![]() |
28f667c7c4 | ||
7e72b74713 | |||
44a386b88c | |||
65aaa13a00 | |||
![]() |
35cbf3b5dc | ||
251234ad43 | |||
d290bdd42a | |||
a331d79900 | |||
76c1a91cfa | |||
6c4a7e0ac3 | |||
c1c97c3d4a | |||
2816b22b38 | |||
1760b8c59f | |||
d7f05fd445 | |||
5cc7e2ae16 | |||
![]() |
a39a6517af | ||
a0a59972e7 | |||
3cd147b49f | |||
1f1520a045 | |||
89d49ae218 | |||
221a7002a9 | |||
bfdcb6bed6 | |||
1c62ba80b1 | |||
101f00e696 | |||
a444c7e0e2 | |||
d809a0260e | |||
fda754145a | |||
62103e7d42 | |||
746684519b | |||
f96a689b3b | |||
![]() |
8fd9516a71 | ||
0fe8239470 | |||
a6c14faa06 | |||
76b3aac802 | |||
59d7fbb052 | |||
156319d2b3 | |||
842e817bf7 | |||
c3994aa443 | |||
f2acfb460f | |||
b7d603b41c | |||
cad1ddc1e8 | |||
2fc8daff10 | |||
a2f075b996 | |||
75ded99ff9 | |||
23c52d9584 | |||
e491573060 | |||
1f232e9ae9 | |||
f915549ee7 | |||
4ffa5e5703 | |||
398d0bf57e | |||
7fc60bff14 | |||
219049bb3b | |||
20614d331d | |||
6adb254bb0 | |||
d923fb784f | |||
74fcb531de | |||
27941b027b | |||
795a874d0b | |||
c565d0764f | |||
a250be980a | |||
96825403a6 | |||
95a018aa32 | |||
c87dd76937 | |||
493c623b13 | |||
adc6659de5 | |||
40d90456ea | |||
f8ca1da138 | |||
1b7ceb0aff | |||
53ff71725a | |||
b6279b7415 | |||
e77821eeca | |||
774b61189c | |||
841b0c2bf5 | |||
42224bf623 | |||
03faffa10b | |||
f1f68b3f9a | |||
19c7ef3067 | |||
cbd6c5735d | |||
0f0436c15e | |||
ab93e568eb | |||
0733bd0d64 | |||
27e39cc533 | |||
9029690a5d | |||
b374fcc98f | |||
8cb10c124e | |||
67ddf68dd9 | |||
e9bf624a49 | |||
db600fd639 | |||
2a68b41b7d | |||
e22e766cf8 | |||
81bb2a143c | |||
dac6091207 | |||
0438944b34 | |||
e3d575b376 | |||
d34c5eec19 | |||
![]() |
79a58eef05 | ||
a1420da027 | |||
a9dd6d004b | |||
816597d6da | |||
8a506b9660 | |||
dcb443416e | |||
7ef2dd8424 | |||
675d42dfc3 | |||
737a4309e8 | |||
cdd406f4bd | |||
13876d50ce | |||
3ea4d3dc07 | |||
70a6c737ec | |||
3468434b6b | |||
90d3fe1e4d | |||
ec263547b5 | |||
![]() |
5d9d246851 | ||
![]() |
502b8e0f08 | ||
a703bbb4d7 | |||
ef19cd395f | |||
0301aff285 | |||
e322f7a3a2 | |||
002752f021 | |||
1685f5824d | |||
bc0ed16537 | |||
d409ce1593 | |||
32cd853294 | |||
f0221ff667 | |||
e0d7b6c78d | |||
e08ac50a5c | |||
851baa40a1 | |||
03a931a876 | |||
ed8184cff0 | |||
3b0d86d8b1 | |||
e9a3a1afd1 | |||
f49ffd7f1c | |||
11a6d840da | |||
![]() |
eb46b55e56 | ||
4dc534aa04 | |||
f250b1f5a0 | |||
ec574b5b09 | |||
b79a5bdd5a | |||
8f86da71fe | |||
fe513a5b61 | |||
7af84255c7 | |||
debd8aab4a | |||
f83ccbc673 | |||
549b854187 | |||
7d1c7a6485 | |||
![]() |
5fb4ff7711 | ||
![]() |
69a2af7e84 | ||
![]() |
b9ec9afce1 | ||
7de86ad61f | |||
0f6044610f | |||
d9db8f8b7c | |||
e21fdfc8e4 | |||
d6de81eed6 | |||
![]() |
54736d5058 | ||
![]() |
9ca1b721b4 | ||
8fcbbcf2e6 | |||
6547d9d3e2 | |||
![]() |
c1edbe7917 | ||
![]() |
bdf260a1b8 | ||
![]() |
04828b7d99 | ||
69419b5f00 | |||
ad3bcee081 | |||
![]() |
51e73e9956 | ||
530008df1d | |||
e17bee5b7f | |||
44b9f6a888 | |||
5e05db3419 | |||
0d4eefd231 | |||
1bb241437c | |||
92113e2da7 | |||
af91bbc221 | |||
e74535df08 | |||
04f006ea9e | |||
47f46637be | |||
7dd8c889f1 | |||
f881ff129f | |||
f12589d335 | |||
bb9a282c7e | |||
21c658b718 | |||
bf49bb354f | |||
7fbd9b67af | |||
e90d8422d0 | |||
65f674b570 | |||
dc66fa5c9c | |||
d4ead6e639 | |||
00466e756e | |||
7bfb7450a2 | |||
de47bf69da | |||
b800a05c55 | |||
![]() |
50dd876fbf | ||
2ed2dd7b13 | |||
![]() |
cc9bee9162 | ||
![]() |
35b1cc806f |
@@ -138,11 +138,6 @@ get_blender_version()
|
||||
#-----------------------------------------------------------------------------
|
||||
# Options
|
||||
|
||||
# First platform specific non-cached vars
|
||||
if(UNIX AND NOT (APPLE OR HAIKU))
|
||||
set(WITH_X11 ON)
|
||||
endif()
|
||||
|
||||
# Blender internal features
|
||||
option(WITH_BLENDER "Build blender (disable to build only the blender player)" ON)
|
||||
mark_as_advanced(WITH_BLENDER)
|
||||
@@ -207,7 +202,15 @@ mark_as_advanced(WITH_GHOST_DEBUG)
|
||||
option(WITH_GHOST_SDL "Enable building Blender against SDL for windowing rather than the native APIs" OFF)
|
||||
mark_as_advanced(WITH_GHOST_SDL)
|
||||
|
||||
if(WITH_X11)
|
||||
if(UNIX AND NOT (APPLE OR HAIKU))
|
||||
option(WITH_GHOST_X11 "Enable building Blender against X11 for windowing" ON)
|
||||
mark_as_advanced(WITH_GHOST_X11)
|
||||
|
||||
option(WITH_GHOST_WAYLAND "Enable building Blender against Wayland for windowing (under development)" OFF)
|
||||
mark_as_advanced(WITH_GHOST_WAYLAND)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_X11)
|
||||
option(WITH_GHOST_XDND "Enable drag'n'drop support on X11 using XDND protocol" ON)
|
||||
endif()
|
||||
|
||||
@@ -232,7 +235,7 @@ if(UNIX AND NOT APPLE)
|
||||
mark_as_advanced(WITH_OPENMP_STATIC)
|
||||
endif()
|
||||
|
||||
if(WITH_X11)
|
||||
if(WITH_GHOST_X11)
|
||||
option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON)
|
||||
option(WITH_X11_XF86VMODE "Enable X11 video mode switching" ON)
|
||||
option(WITH_X11_XFIXES "Enable X11 XWayland cursor warping workaround" ON)
|
||||
@@ -323,6 +326,10 @@ option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
|
||||
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)
|
||||
@@ -429,6 +436,8 @@ endif()
|
||||
option(WITH_GTESTS "Enable GTest unit testing" OFF)
|
||||
option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF)
|
||||
option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF)
|
||||
set(TEST_PYTHON_EXE "" CACHE PATH "Python executable to run unit tests")
|
||||
mark_as_advanced(TEST_PYTHON_EXE)
|
||||
|
||||
# Documentation
|
||||
if(UNIX AND NOT APPLE)
|
||||
@@ -469,6 +478,8 @@ endif()
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
option(WITH_LINKER_GOLD "Use ld.gold linker which is usually faster than ld.bfd" ON)
|
||||
mark_as_advanced(WITH_LINKER_GOLD)
|
||||
option(WITH_LINKER_LLD "Use ld.lld linker which is usually faster than ld.gold" OFF)
|
||||
mark_as_advanced(WITH_LINKER_LLD)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
@@ -532,6 +543,15 @@ if(WIN32)
|
||||
option(WITH_WINDOWS_BUNDLE_CRT "Bundle the C runtime for install free distribution." ON)
|
||||
mark_as_advanced(WITH_WINDOWS_BUNDLE_CRT)
|
||||
|
||||
option(WITH_WINDOWS_SCCACHE "Use sccache to speed up builds (Ninja builder only)" OFF)
|
||||
mark_as_advanced(WITH_WINDOWS_SCCACHE)
|
||||
|
||||
option(WITH_WINDOWS_PDB "Generate a pdb file for client side stacktraces" ON)
|
||||
mark_as_advanced(WITH_WINDOWS_PDB)
|
||||
|
||||
option(WITH_WINDOWS_STRIPPED_PDB "Use a stripped PDB file" On)
|
||||
mark_as_advanced(WITH_WINDOWS_STRIPPED_PDB)
|
||||
|
||||
endif()
|
||||
|
||||
# The following only works with the Ninja generator in CMake >= 3.0.
|
||||
@@ -678,7 +698,8 @@ if(WITH_INSTALL_PORTABLE)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_SDL OR WITH_HEADLESS)
|
||||
set(WITH_X11 OFF)
|
||||
set(WITH_GHOST_WAYLAND OFF)
|
||||
set(WITH_GHOST_X11 OFF)
|
||||
set(WITH_X11_XINPUT OFF)
|
||||
set(WITH_X11_XF86VMODE OFF)
|
||||
set(WITH_X11_XFIXES OFF)
|
||||
|
50
GNUmakefile
50
GNUmakefile
@@ -71,17 +71,6 @@ Testing Targets
|
||||
which are tagged to use the stricter formatting
|
||||
* test_deprecated:
|
||||
Checks for deprecation tags in our code which may need to be removed
|
||||
* test_style_c:
|
||||
Checks C/C++ conforms with blenders style guide:
|
||||
https://wiki.blender.org/wiki/Source/Code_Style
|
||||
* test_style_c_qtc:
|
||||
Same as test_style but outputs QtCreator tasks format
|
||||
* test_style_osl:
|
||||
Checks OpenShadingLanguage conforms with blenders style guide:
|
||||
https://wiki.blender.org/wiki/Source/Code_Style
|
||||
* test_style_osl_qtc:
|
||||
Checks OpenShadingLanguage conforms with blenders style guide:
|
||||
https://wiki.blender.org/wiki/Source/Code_Style
|
||||
|
||||
Static Source Code Checking
|
||||
Not associated with building Blender.
|
||||
@@ -402,45 +391,6 @@ test_cmake: .FORCE
|
||||
test_deprecated: .FORCE
|
||||
$(PYTHON) tests/check_deprecated.py
|
||||
|
||||
test_style_c: .FORCE
|
||||
# run our own checks on C/C++ style
|
||||
PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
|
||||
"$(BLENDER_DIR)/source/blender" \
|
||||
"$(BLENDER_DIR)/source/creator" \
|
||||
--no-length-check
|
||||
|
||||
test_style_c_qtc: .FORCE
|
||||
# run our own checks on C/C++ style
|
||||
USE_QTC_TASK=1 \
|
||||
PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
|
||||
"$(BLENDER_DIR)/source/blender" \
|
||||
"$(BLENDER_DIR)/source/creator" \
|
||||
--no-length-check \
|
||||
> \
|
||||
"$(BLENDER_DIR)/test_style.tasks"
|
||||
@echo "written: test_style.tasks"
|
||||
|
||||
|
||||
test_style_osl: .FORCE
|
||||
# run our own checks on C/C++ style
|
||||
PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
|
||||
"$(BLENDER_DIR)/intern/cycles/kernel/shaders" \
|
||||
"$(BLENDER_DIR)/release/scripts/templates_osl"
|
||||
|
||||
|
||||
test_style_osl_qtc: .FORCE
|
||||
# run our own checks on C/C++ style
|
||||
USE_QTC_TASK=1 \
|
||||
PYTHONIOENCODING=utf_8 $(PYTHON) \
|
||||
"$(BLENDER_DIR)/source/tools/check_source/check_style_c.py" \
|
||||
"$(BLENDER_DIR)/intern/cycles/kernel/shaders" \
|
||||
"$(BLENDER_DIR)/release/scripts/templates_osl" \
|
||||
> \
|
||||
"$(BLENDER_DIR)/test_style.tasks"
|
||||
@echo "written: test_style.tasks"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Project Files
|
||||
|
@@ -25,6 +25,8 @@ if(UNIX AND NOT APPLE)
|
||||
set(BZIP2_CFLAGS "-fPIC -Wall -Winline -O2 -g -D_FILE_OFFSET_BITS=64")
|
||||
set(BZIP2_CONFIGURE_ENV ${BZIP2_CONFIGURE_ENV} && export LDFLAGS=${BZIP2_LDFLAGS} && export CFLAGS=${BZIP2_CFLAGS}
|
||||
&& export PREFIX=${BZIP2_PREFIX})
|
||||
else()
|
||||
set(BZIP2_CONFIGURE_ENV ${CONFIGURE_ENV})
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(external_bzip2
|
||||
|
@@ -2654,7 +2654,7 @@ compile_USD() {
|
||||
|
||||
cd $CWD
|
||||
INFO "Done compiling USD-$USD_VERSION!"
|
||||
_is_building=true
|
||||
_is_building=false
|
||||
else
|
||||
INFO "Own USD-$USD_VERSION is up to date, nothing to do!"
|
||||
INFO "If you want to force rebuild of this lib, use the --force-usd option."
|
||||
@@ -5354,6 +5354,11 @@ print_info() {
|
||||
_1="-D WITH_USD=ON"
|
||||
PRINT " $_1"
|
||||
_buildargs="$_buildargs $_1"
|
||||
if [ -d $INST/usd ]; then
|
||||
_1="-D USD_ROOT_DIR=$INST/usd"
|
||||
PRINT " $_1"
|
||||
_buildargs="$_buildargs $_1"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$NO_SYSTEM_GLEW" = true ]; then
|
||||
|
@@ -49,7 +49,6 @@ if(NOT LLVM_ROOT_DIR)
|
||||
OUTPUT_VARIABLE LLVM_ROOT_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(LLVM_ROOT_DIR ${LLVM_ROOT_DIR} CACHE PATH "Path to the LLVM installation")
|
||||
set(LLVM_INCLUDE_DIRS ${LLVM_ROOT_DIR}/include CACHE PATH "Path to the LLVM include directory")
|
||||
endif()
|
||||
if(NOT LLVM_LIBPATH)
|
||||
execute_process(COMMAND ${LLVM_CONFIG} --libdir
|
||||
|
@@ -66,6 +66,9 @@ macro(BLENDER_SRC_GTEST_EX)
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(${TARGET_NAME} bf_intern_libc_compat)
|
||||
endif()
|
||||
if(WITH_TBB)
|
||||
target_link_libraries(${TARGET_NAME} ${TBB_LIBRARIES})
|
||||
endif()
|
||||
|
||||
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(GENERATOR_IS_MULTI_CONFIG)
|
||||
|
@@ -440,6 +440,14 @@ function(SETUP_LIBDIRS)
|
||||
link_directories(${HDF5_LIBPATH})
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_WAYLAND)
|
||||
link_directories(
|
||||
${wayland-client_LIBRARY_DIRS}
|
||||
${wayland-egl_LIBRARY_DIRS}
|
||||
${xkbcommon_LIBRARY_DIRS}
|
||||
${wayland-cursor_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
if(WIN32 AND NOT UNIX)
|
||||
link_directories(${PTHREADS_LIBPATH})
|
||||
endif()
|
||||
|
@@ -504,7 +504,27 @@ if(WITH_SYSTEM_AUDASPACE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_X11)
|
||||
if(WITH_GHOST_WAYLAND)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(wayland-client REQUIRED wayland-client>=1.12)
|
||||
pkg_check_modules(wayland-egl REQUIRED wayland-egl)
|
||||
pkg_check_modules(wayland-scanner REQUIRED wayland-scanner)
|
||||
pkg_check_modules(xkbcommon REQUIRED xkbcommon)
|
||||
pkg_check_modules(wayland-cursor REQUIRED wayland-cursor)
|
||||
|
||||
set(WITH_GL_EGL ON)
|
||||
|
||||
if(WITH_GHOST_WAYLAND)
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
${wayland-client_LIBRARIES}
|
||||
${wayland-egl_LIBRARIES}
|
||||
${xkbcommon_LIBRARIES}
|
||||
${wayland-cursor_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_X11)
|
||||
find_package(X11 REQUIRED)
|
||||
|
||||
find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH})
|
||||
@@ -575,6 +595,19 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
unset(LD_VERSION)
|
||||
endif()
|
||||
|
||||
if(WITH_LINKER_LLD)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_C_COMPILER} -fuse-ld=lld -Wl,--version
|
||||
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
||||
if("${LD_VERSION}" MATCHES "LLD")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=lld")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld")
|
||||
else()
|
||||
message(STATUS "LLD linker isn't available, using the default system linker.")
|
||||
endif()
|
||||
unset(LD_VERSION)
|
||||
endif()
|
||||
|
||||
# CLang is the same as GCC for now.
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
|
||||
|
@@ -51,6 +51,10 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
endif()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \"${CLANG_OPENMP_LIB}\"")
|
||||
endif()
|
||||
if(WITH_WINDOWS_STRIPPED_PDB)
|
||||
message(WARNING "stripped pdb not supported with clang, disabling..")
|
||||
set(WITH_WINDOWS_STRIPPED_PDB Off)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ${WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS})
|
||||
@@ -112,7 +116,7 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SAFESEH:NO")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /SAFESEH:NO")
|
||||
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 Comctl32
|
||||
ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 Comctl32 version
|
||||
advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp Shlwapi
|
||||
)
|
||||
|
||||
@@ -134,7 +138,12 @@ add_definitions(-D_ALLOW_KEYWORD_MACROS)
|
||||
# We want to support Windows 7 level ABI
|
||||
add_definitions(-D_WIN32_WINNT=0x601)
|
||||
include(build_files/cmake/platform/platform_win32_bundle_crt.cmake)
|
||||
remove_cc_flag("/MDd" "/MD")
|
||||
remove_cc_flag("/MDd" "/MD" "/Zi")
|
||||
|
||||
if(WITH_WINDOWS_PDB)
|
||||
set(PDB_INFO_OVERRIDE_FLAGS "/Z7")
|
||||
set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
|
||||
endif()
|
||||
|
||||
if(MSVC_CLANG) # Clangs version of cl doesn't support all flags
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ")
|
||||
@@ -151,16 +160,30 @@ if(MSVC_VERSION GREATER 1911 AND NOT MSVC_CLANG)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:twoPhase-")
|
||||
endif()
|
||||
|
||||
if(WITH_WINDOWS_SCCACHE AND CMAKE_VS_MSBUILD_COMMAND)
|
||||
message(WARNING "Disabling sccache, sccache is not supported with msbuild")
|
||||
set(WITH_WINDOWS_SCCACHE Off)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd /ZI")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd /ZI")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD")
|
||||
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MD")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MD")
|
||||
if(WITH_WINDOWS_SCCACHE)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER sccache)
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER sccache)
|
||||
set(SYMBOL_FORMAT /Z7)
|
||||
else()
|
||||
unset(CMAKE_C_COMPILER_LAUNCHER)
|
||||
unset(CMAKE_CXX_COMPILER_LAUNCHER)
|
||||
set(SYMBOL_FORMAT /ZI)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd ${SYMBOL_FORMAT}")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd ${SYMBOL_FORMAT}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD ${PDB_INFO_OVERRIDE_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD ${PDB_INFO_OVERRIDE_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD ${PDB_INFO_OVERRIDE_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MD ${PDB_INFO_OVERRIDE_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD ${SYMBOL_FORMAT}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MD ${SYMBOL_FORMAT}")
|
||||
unset(SYMBOL_FORMAT)
|
||||
# JMC is available on msvc 15.8 (1915) and up
|
||||
if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /JMC")
|
||||
@@ -172,6 +195,7 @@ set(PLATFORM_LINKFLAGS_DEBUG "${PLATFORM_LINKFLAGS_DEBUG} /IGNORE:4099 /NODEFAUL
|
||||
|
||||
# Ignore meaningless for us linker warnings.
|
||||
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /ignore:4049 /ignore:4217 /ignore:4221")
|
||||
set(PLATFORM_LINKFLAGS_RELEASE "${PLATFORM_LINKFLAGS} ${PDB_INFO_OVERRIDE_LINKER_FLAGS}")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
|
||||
|
||||
if(CMAKE_CL_64)
|
||||
@@ -209,7 +233,7 @@ endif()
|
||||
|
||||
# Mark libdir as system headers with a lower warn level, to resolve some warnings
|
||||
# that we have very little control over
|
||||
if(MSVC_VERSION GREATER_EQUAL 1914 AND NOT MSVC_CLANG)
|
||||
if(MSVC_VERSION GREATER_EQUAL 1914 AND NOT MSVC_CLANG AND NOT WITH_WINDOWS_SCCACHE)
|
||||
add_compile_options(/experimental:external /external:templates- /external:I "${LIBDIR}" /external:W0)
|
||||
endif()
|
||||
|
||||
|
@@ -2,6 +2,11 @@ set BUILD_GENERATOR_POST=
|
||||
set BUILD_PLATFORM_SELECT=
|
||||
set MSBUILD_PLATFORM=x64
|
||||
|
||||
if "%BUILD_WITH_SCCACHE%"=="1" (
|
||||
echo sccache is only supported with ninja as the build system.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if "%WITH_CLANG%"=="1" (
|
||||
set CLANG_CMAKE_ARGS=-T"llvm"
|
||||
if "%WITH_ASAN%"=="1" (
|
||||
|
@@ -6,6 +6,13 @@ if %ERRORLEVEL% NEQ 0 (
|
||||
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Ninja" %TESTS_CMAKE_ARGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE%
|
||||
|
||||
if "%BUILD_WITH_SCCACHE%"=="1" (
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_WINDOWS_SCCACHE=On
|
||||
if NOT "%verbose%" == "" (
|
||||
echo Enabling sccache
|
||||
)
|
||||
)
|
||||
|
||||
if "%WITH_CLANG%" == "1" (
|
||||
set LLVM_DIR=
|
||||
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\LLVM\LLVM" /ve 2^>nul`) DO set LLVM_DIR=%%C
|
||||
|
@@ -86,6 +86,8 @@ if NOT "%1" == "" (
|
||||
set BUILD_UPDATE_ARGS="--no-libraries"
|
||||
) else if "%1" == "ninja" (
|
||||
SET BUILD_WITH_NINJA=1
|
||||
) else if "%1" == "sccache" (
|
||||
SET BUILD_WITH_SCCACHE=1
|
||||
) else if "%1" == "clean" (
|
||||
set MUST_CLEAN=1
|
||||
) else if "%1" == "verbose" (
|
||||
|
@@ -30,3 +30,4 @@ set WITH_PYDEBUG=
|
||||
set PYDEBUG_CMAKE_ARGS=
|
||||
set FORMAT=
|
||||
set TEST=
|
||||
set BUILD_WITH_SCCACHE=
|
||||
|
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "V2.83"
|
||||
PROJECT_NUMBER = "V2.90"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
2
extern/CMakeLists.txt
vendored
2
extern/CMakeLists.txt
vendored
@@ -72,7 +72,7 @@ if(WITH_CYCLES OR WITH_COMPOSITOR OR WITH_OPENSUBDIV)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_X11 AND WITH_GHOST_XDND)
|
||||
if(WITH_GHOST_X11 AND WITH_GHOST_XDND)
|
||||
add_subdirectory(xdnd)
|
||||
endif()
|
||||
|
||||
|
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
@@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
#define MANTA_GIT_VERSION "commit 21303fab2eda588ec22988bf9e5762d2001c131f"
|
||||
#define MANTA_GIT_VERSION "commit b4a2742bd743e2913fba94dd35846042e2650212"
|
||||
|
@@ -244,13 +244,15 @@ struct KnApplyForce : public KernelBase {
|
||||
bool additive;
|
||||
};
|
||||
|
||||
//! add gravity forces to all fluid cells, automatically adapts to different grid sizes
|
||||
//! add gravity forces to all fluid cells, optionally adapts to different grid sizes automatically
|
||||
void addGravity(const FlagGrid &flags,
|
||||
MACGrid &vel,
|
||||
Vec3 gravity,
|
||||
const Grid<Real> *exclude = NULL)
|
||||
const Grid<Real> *exclude = NULL,
|
||||
bool scale = true)
|
||||
{
|
||||
Vec3 f = gravity * flags.getParent()->getDt() / flags.getDx();
|
||||
float gridScale = (scale) ? flags.getDx() : 1;
|
||||
Vec3 f = gravity * flags.getParent()->getDt() / gridScale;
|
||||
KnApplyForce(flags, vel, f, exclude, true);
|
||||
}
|
||||
static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
|
||||
@@ -267,8 +269,9 @@ static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
|
||||
MACGrid &vel = *_args.getPtr<MACGrid>("vel", 1, &_lock);
|
||||
Vec3 gravity = _args.get<Vec3>("gravity", 2, &_lock);
|
||||
const Grid<Real> *exclude = _args.getPtrOpt<Grid<Real>>("exclude", 3, NULL, &_lock);
|
||||
bool scale = _args.getOpt<bool>("scale", 4, true, &_lock);
|
||||
_retval = getPyNone();
|
||||
addGravity(flags, vel, gravity, exclude);
|
||||
addGravity(flags, vel, gravity, exclude, scale);
|
||||
_args.check();
|
||||
}
|
||||
pbFinalizePlugin(parent, "addGravity", !noTiming);
|
||||
@@ -287,14 +290,13 @@ void PbRegister_addGravity()
|
||||
}
|
||||
}
|
||||
|
||||
//! add gravity forces to all fluid cells , but dont account for changing cell size
|
||||
//! Deprecated: use addGravity(scale=false) instead
|
||||
void addGravityNoScale(const FlagGrid &flags,
|
||||
MACGrid &vel,
|
||||
const Vec3 &gravity,
|
||||
const Grid<Real> *exclude = NULL)
|
||||
{
|
||||
const Vec3 f = gravity * flags.getParent()->getDt();
|
||||
KnApplyForce(flags, vel, f, exclude, true);
|
||||
addGravity(flags, vel, gravity, exclude, false);
|
||||
}
|
||||
static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
|
||||
{
|
||||
@@ -412,14 +414,17 @@ struct KnAddBuoyancy : public KernelBase {
|
||||
Vec3 strength;
|
||||
};
|
||||
|
||||
//! add Buoyancy force based on fctor (e.g. smoke density)
|
||||
//! add Buoyancy force based on factor (e.g. smoke density), optionally adapts to different grid
|
||||
//! sizes automatically
|
||||
void addBuoyancy(const FlagGrid &flags,
|
||||
const Grid<Real> &density,
|
||||
MACGrid &vel,
|
||||
Vec3 gravity,
|
||||
Real coefficient = 1.)
|
||||
Real coefficient = 1.,
|
||||
bool scale = true)
|
||||
{
|
||||
Vec3 f = -gravity * flags.getParent()->getDt() / flags.getParent()->getDx() * coefficient;
|
||||
float gridScale = (scale) ? flags.getDx() : 1;
|
||||
Vec3 f = -gravity * flags.getParent()->getDt() / gridScale * coefficient;
|
||||
KnAddBuoyancy(flags, density, vel, f);
|
||||
}
|
||||
static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
|
||||
@@ -437,8 +442,9 @@ static PyObject *_W_2(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
|
||||
MACGrid &vel = *_args.getPtr<MACGrid>("vel", 2, &_lock);
|
||||
Vec3 gravity = _args.get<Vec3>("gravity", 3, &_lock);
|
||||
Real coefficient = _args.getOpt<Real>("coefficient", 4, 1., &_lock);
|
||||
bool scale = _args.getOpt<bool>("scale", 5, true, &_lock);
|
||||
_retval = getPyNone();
|
||||
addBuoyancy(flags, density, vel, gravity, coefficient);
|
||||
addBuoyancy(flags, density, vel, gravity, coefficient, scale);
|
||||
_args.check();
|
||||
}
|
||||
pbFinalizePlugin(parent, "addBuoyancy", !noTiming);
|
||||
|
@@ -20,7 +20,6 @@
|
||||
|
||||
# add_subdirectory(atomic) # header only
|
||||
add_subdirectory(clog)
|
||||
add_subdirectory(string)
|
||||
add_subdirectory(ghost)
|
||||
add_subdirectory(guardedalloc)
|
||||
add_subdirectory(libmv)
|
||||
|
@@ -500,8 +500,9 @@ class CYCLES_RENDER_PT_light_paths_caustics(CyclesButtonsPanel, Panel):
|
||||
|
||||
col = layout.column()
|
||||
col.prop(cscene, "blur_glossy")
|
||||
col.prop(cscene, "caustics_reflective")
|
||||
col.prop(cscene, "caustics_refractive")
|
||||
col = layout.column(heading="Caustics", align=True)
|
||||
col.prop(cscene, "caustics_reflective", text="Reflective")
|
||||
col.prop(cscene, "caustics_refractive", text="Refractive")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
|
||||
@@ -762,22 +763,16 @@ class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel):
|
||||
rd = scene.render
|
||||
view_layer = context.view_layer
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
|
||||
col = flow.column()
|
||||
col = layout.column(heading="Include")
|
||||
col.prop(view_layer, "use_sky", text="Environment")
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_ao", text="Ambient Occlusion")
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_solid", text="Surfaces")
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_strand", text="Hair")
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_volumes", text="Volumes")
|
||||
if with_freestyle:
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_freestyle", text="Freestyle")
|
||||
col.active = rd.use_freestyle
|
||||
sub = col.row(align=True)
|
||||
sub.prop(view_layer, "use_freestyle", text="Freestyle")
|
||||
sub.active = rd.use_freestyle
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_override(CyclesButtonsPanel, Panel):
|
||||
@@ -819,36 +814,27 @@ class CYCLES_RENDER_PT_passes_data(CyclesButtonsPanel, Panel):
|
||||
view_layer = context.view_layer
|
||||
cycles_view_layer = view_layer.cycles
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
col = flow.column()
|
||||
col = layout.column(heading="Include", align=True)
|
||||
col.prop(view_layer, "use_pass_combined")
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_pass_z")
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_pass_mist")
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_pass_normal")
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_pass_vector")
|
||||
col.active = not rd.use_motion_blur
|
||||
col = flow.column()
|
||||
sub = col.column()
|
||||
sub.active = not rd.use_motion_blur
|
||||
sub.prop(view_layer, "use_pass_vector")
|
||||
col.prop(view_layer, "use_pass_uv")
|
||||
col = flow.column()
|
||||
|
||||
col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data")
|
||||
|
||||
col = layout.column(heading="Indexes", align=True)
|
||||
col.prop(view_layer, "use_pass_object_index")
|
||||
col = flow.column()
|
||||
col.prop(view_layer, "use_pass_material_index")
|
||||
|
||||
layout.separator()
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
col = flow.column()
|
||||
col.prop(cycles_view_layer, "denoising_store_passes", text="Denoising Data")
|
||||
col = flow.column()
|
||||
col = layout.column(heading="Debug", align=True)
|
||||
col.prop(cycles_view_layer, "pass_debug_render_time", text="Render Time")
|
||||
col = flow.column()
|
||||
col.prop(cycles_view_layer, "pass_debug_sample_count", text="Sample Count")
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
||||
layout.prop(view_layer, "pass_alpha_threshold")
|
||||
|
||||
@@ -866,38 +852,26 @@ class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel):
|
||||
view_layer = context.view_layer
|
||||
cycles_view_layer = view_layer.cycles
|
||||
|
||||
split = layout.split(factor=0.35)
|
||||
split.use_property_split = False
|
||||
split.label(text="Diffuse")
|
||||
row = split.row(align=True)
|
||||
row.prop(view_layer, "use_pass_diffuse_direct", text="Direct", toggle=True)
|
||||
row.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
|
||||
row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True)
|
||||
col = layout.column(heading="Diffuse", align=True)
|
||||
col.prop(view_layer, "use_pass_diffuse_direct", text="Direct")
|
||||
col.prop(view_layer, "use_pass_diffuse_indirect", text="Indirect")
|
||||
col.prop(view_layer, "use_pass_diffuse_color", text="Color")
|
||||
|
||||
split = layout.split(factor=0.35)
|
||||
split.use_property_split = False
|
||||
split.label(text="Glossy")
|
||||
row = split.row(align=True)
|
||||
row.prop(view_layer, "use_pass_glossy_direct", text="Direct", toggle=True)
|
||||
row.prop(view_layer, "use_pass_glossy_indirect", text="Indirect", toggle=True)
|
||||
row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True)
|
||||
col = layout.column(heading="Glossy", align=True)
|
||||
col.prop(view_layer, "use_pass_glossy_direct", text="Direct")
|
||||
col.prop(view_layer, "use_pass_glossy_indirect", text="Indirect")
|
||||
col.prop(view_layer, "use_pass_glossy_color", text="Color")
|
||||
|
||||
split = layout.split(factor=0.35)
|
||||
split.use_property_split = False
|
||||
split.label(text="Transmission")
|
||||
row = split.row(align=True)
|
||||
row.prop(view_layer, "use_pass_transmission_direct", text="Direct", toggle=True)
|
||||
row.prop(view_layer, "use_pass_transmission_indirect", text="Indirect", toggle=True)
|
||||
row.prop(view_layer, "use_pass_transmission_color", text="Color", toggle=True)
|
||||
col = layout.column(heading="Transmission", align=True)
|
||||
col.prop(view_layer, "use_pass_transmission_direct", text="Direct")
|
||||
col.prop(view_layer, "use_pass_transmission_indirect", text="Indirect")
|
||||
col.prop(view_layer, "use_pass_transmission_color", text="Color")
|
||||
|
||||
split = layout.split(factor=0.35)
|
||||
split.use_property_split = False
|
||||
split.label(text="Volume")
|
||||
row = split.row(align=True)
|
||||
row.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct", toggle=True)
|
||||
row.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect", toggle=True)
|
||||
col = layout.column(heading="Volume", align=True)
|
||||
col.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct")
|
||||
col.prop(cycles_view_layer, "use_pass_volume_indirect", text="Indirect")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col = layout.column(heading="Other", align=True)
|
||||
col.prop(view_layer, "use_pass_emit", text="Emission")
|
||||
col.prop(view_layer, "use_pass_environment")
|
||||
col.prop(view_layer, "use_pass_shadow")
|
||||
@@ -918,11 +892,10 @@ class CYCLES_RENDER_PT_passes_crypto(CyclesButtonsPanel, Panel):
|
||||
|
||||
cycles_view_layer = context.view_layer.cycles
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.use_property_split = False
|
||||
row.prop(cycles_view_layer, "use_pass_crypto_object", text="Object", toggle=True)
|
||||
row.prop(cycles_view_layer, "use_pass_crypto_material", text="Material", toggle=True)
|
||||
row.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset", toggle=True)
|
||||
col = layout.column(heading="Include", align=True)
|
||||
col.prop(cycles_view_layer, "use_pass_crypto_object", text="Object")
|
||||
col.prop(cycles_view_layer, "use_pass_crypto_material", text="Material")
|
||||
col.prop(cycles_view_layer, "use_pass_crypto_asset", text="Asset")
|
||||
|
||||
layout.prop(cycles_view_layer, "pass_crypto_depth", text="Levels")
|
||||
|
||||
@@ -1012,10 +985,9 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
|
||||
view_layer = context.view_layer
|
||||
cycles_view_layer = view_layer.cycles
|
||||
|
||||
split = layout.split()
|
||||
split.active = cycles_view_layer.use_denoising
|
||||
layout.active = cycles_view_layer.use_denoising
|
||||
|
||||
col = split.column(align=True)
|
||||
col = layout.column()
|
||||
|
||||
if show_optix_denoising(context):
|
||||
col.prop(cycles_view_layer, "use_optix_denoising")
|
||||
@@ -1026,51 +998,29 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
|
||||
return
|
||||
|
||||
col.prop(cycles_view_layer, "denoising_radius", text="Radius")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(cycles_view_layer, "denoising_strength", slider=True, text="Strength")
|
||||
col.prop(cycles_view_layer, "denoising_feature_strength", slider=True, text="Feature Strength")
|
||||
col.prop(cycles_view_layer, "denoising_relative_pca")
|
||||
|
||||
layout.separator()
|
||||
|
||||
split = layout.split(factor=0.5)
|
||||
split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
|
||||
col = layout.column()
|
||||
col.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
|
||||
|
||||
col = split.column()
|
||||
col.alignment = 'RIGHT'
|
||||
col.label(text="Diffuse")
|
||||
|
||||
row = split.row(align=True)
|
||||
row.use_property_split = False
|
||||
row = col.row(heading="Diffuse", align=True)
|
||||
row.prop(cycles_view_layer, "denoising_diffuse_direct", text="Direct", toggle=True)
|
||||
row.prop(cycles_view_layer, "denoising_diffuse_indirect", text="Indirect", toggle=True)
|
||||
|
||||
split = layout.split(factor=0.5)
|
||||
split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
|
||||
|
||||
col = split.column()
|
||||
col.alignment = 'RIGHT'
|
||||
col.label(text="Glossy")
|
||||
|
||||
row = split.row(align=True)
|
||||
row.use_property_split = False
|
||||
row = col.row(heading="Glossy", align=True)
|
||||
row.prop(cycles_view_layer, "denoising_glossy_direct", text="Direct", toggle=True)
|
||||
row.prop(cycles_view_layer, "denoising_glossy_indirect", text="Indirect", toggle=True)
|
||||
|
||||
split = layout.split(factor=0.5)
|
||||
split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
|
||||
|
||||
col = split.column()
|
||||
col.alignment = 'RIGHT'
|
||||
col.label(text="Transmission")
|
||||
|
||||
row = split.row(align=True)
|
||||
row.use_property_split = False
|
||||
row = col.row(heading="Transmission", align=True)
|
||||
row.prop(cycles_view_layer, "denoising_transmission_direct", text="Direct", toggle=True)
|
||||
row.prop(cycles_view_layer, "denoising_transmission_indirect", text="Indirect", toggle=True)
|
||||
|
||||
split = layout.split(factor=0.5)
|
||||
split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes
|
||||
|
||||
|
||||
class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Post Processing"
|
||||
@@ -1084,7 +1034,7 @@ class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel):
|
||||
|
||||
rd = context.scene.render
|
||||
|
||||
col = layout.column(align=True)
|
||||
col = layout.column(align=True, heading="Pipeline")
|
||||
col.prop(rd, "use_compositing")
|
||||
col.prop(rd, "use_sequencer")
|
||||
|
||||
@@ -1273,22 +1223,18 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
layout = self.layout
|
||||
ob = context.object
|
||||
|
||||
col = flow.column()
|
||||
col.prop(ob, "hide_viewport", text="Show in Viewports", invert_checkbox=True, toggle=False)
|
||||
col = flow.column()
|
||||
col.prop(ob, "hide_render", text="Show in Renders", invert_checkbox=True, toggle=False)
|
||||
col = flow.column()
|
||||
col.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False)
|
||||
layout.prop(ob, "hide_select", text="Selectable", invert_checkbox=True, toggle=False)
|
||||
|
||||
col = layout.column(heading="Show in")
|
||||
col.prop(ob, "hide_viewport", text="Viewports", invert_checkbox=True, toggle=False)
|
||||
col.prop(ob, "hide_render", text="Renders", invert_checkbox=True, toggle=False)
|
||||
|
||||
if has_geometry_visibility(ob):
|
||||
cob = ob.cycles
|
||||
col = flow.column()
|
||||
col = layout.column(heading="Mask")
|
||||
col.prop(cob, "is_shadow_catcher")
|
||||
col = flow.column()
|
||||
col.prop(cob, "is_holdout")
|
||||
|
||||
|
||||
@@ -1312,24 +1258,16 @@ class CYCLES_OBJECT_PT_visibility_ray_visibility(CyclesButtonsPanel, Panel):
|
||||
cob = ob.cycles
|
||||
visibility = ob.cycles_visibility
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
|
||||
col = flow.column()
|
||||
col = layout.column()
|
||||
col.prop(visibility, "camera")
|
||||
col = flow.column()
|
||||
col.prop(visibility, "diffuse")
|
||||
col = flow.column()
|
||||
col.prop(visibility, "glossy")
|
||||
col = flow.column()
|
||||
col.prop(visibility, "transmission")
|
||||
col = flow.column()
|
||||
col.prop(visibility, "scatter")
|
||||
|
||||
if ob.type != 'LIGHT':
|
||||
col = flow.column()
|
||||
col.prop(visibility, "shadow")
|
||||
|
||||
layout.separator()
|
||||
sub = col.column()
|
||||
sub.prop(visibility, "shadow")
|
||||
|
||||
|
||||
class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel):
|
||||
@@ -1352,15 +1290,13 @@ class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel):
|
||||
ob = context.object
|
||||
cob = ob.cycles
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
|
||||
row = layout.row()
|
||||
row.active = scene.render.use_simplify and cscene.use_camera_cull
|
||||
row.prop(cob, "use_camera_cull")
|
||||
|
||||
col = flow.column()
|
||||
col.active = scene.render.use_simplify and cscene.use_camera_cull
|
||||
col.prop(cob, "use_camera_cull")
|
||||
|
||||
col = flow.column()
|
||||
col.active = scene.render.use_simplify and cscene.use_distance_cull
|
||||
col.prop(cob, "use_distance_cull")
|
||||
row = layout.row()
|
||||
row.active = scene.render.use_simplify and cscene.use_distance_cull
|
||||
row.prop(cob, "use_distance_cull")
|
||||
|
||||
|
||||
def panel_node_draw(layout, id_data, output_type, input_name):
|
||||
@@ -1474,6 +1410,8 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
light = context.light
|
||||
panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface')
|
||||
|
||||
@@ -1523,6 +1461,8 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
world = context.world
|
||||
|
||||
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
|
||||
@@ -1542,6 +1482,8 @@ class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
world = context.world
|
||||
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
|
||||
|
||||
@@ -1729,6 +1671,8 @@ class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
mat = context.material
|
||||
if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
|
||||
layout.prop(mat, "diffuse_color")
|
||||
@@ -1747,6 +1691,8 @@ class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
mat = context.material
|
||||
# cmat = mat.cycles
|
||||
|
||||
@@ -1765,6 +1711,8 @@ class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
|
||||
mat = context.material
|
||||
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')
|
||||
|
||||
@@ -1906,26 +1854,24 @@ class CYCLES_RENDER_PT_bake_influence(CyclesButtonsPanel, Panel):
|
||||
sub.prop(cbk, "normal_b", text="B")
|
||||
|
||||
elif cscene.bake_type == 'COMBINED':
|
||||
row = col.row(align=True)
|
||||
row.use_property_split = False
|
||||
row.prop(cbk, "use_pass_direct", toggle=True)
|
||||
row.prop(cbk, "use_pass_indirect", toggle=True)
|
||||
|
||||
flow = col.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=True)
|
||||
col = layout.column(heading="Lighting", align=True)
|
||||
col.prop(cbk, "use_pass_direct")
|
||||
col.prop(cbk, "use_pass_indirect")
|
||||
|
||||
flow.active = cbk.use_pass_direct or cbk.use_pass_indirect
|
||||
flow.prop(cbk, "use_pass_diffuse")
|
||||
flow.prop(cbk, "use_pass_glossy")
|
||||
flow.prop(cbk, "use_pass_transmission")
|
||||
flow.prop(cbk, "use_pass_ambient_occlusion")
|
||||
flow.prop(cbk, "use_pass_emit")
|
||||
col = layout.column(heading="Contributions", align=True)
|
||||
col.active = cbk.use_pass_direct or cbk.use_pass_indirect
|
||||
col.prop(cbk, "use_pass_diffuse")
|
||||
col.prop(cbk, "use_pass_glossy")
|
||||
col.prop(cbk, "use_pass_transmission")
|
||||
col.prop(cbk, "use_pass_ambient_occlusion")
|
||||
col.prop(cbk, "use_pass_emit")
|
||||
|
||||
elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION'}:
|
||||
row = col.row(align=True)
|
||||
row.use_property_split = False
|
||||
row.prop(cbk, "use_pass_direct", toggle=True)
|
||||
row.prop(cbk, "use_pass_indirect", toggle=True)
|
||||
row.prop(cbk, "use_pass_color", toggle=True)
|
||||
col = layout.column(heading="Contributions", align=True)
|
||||
col.prop(cbk, "use_pass_direct")
|
||||
col.prop(cbk, "use_pass_indirect")
|
||||
col.prop(cbk, "use_pass_color")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_bake_selected_to_active(CyclesButtonsPanel, Panel):
|
||||
@@ -2131,17 +2077,17 @@ class CYCLES_RENDER_PT_simplify_culling(CyclesButtonsPanel, Panel):
|
||||
|
||||
layout.active = rd.use_simplify
|
||||
|
||||
col = layout.column()
|
||||
col.prop(cscene, "use_camera_cull")
|
||||
sub = col.column()
|
||||
row = layout.row(heading="Camera Culling")
|
||||
row.prop(cscene, "use_camera_cull", text="")
|
||||
sub = row.column()
|
||||
sub.active = cscene.use_camera_cull
|
||||
sub.prop(cscene, "camera_cull_margin")
|
||||
sub.prop(cscene, "camera_cull_margin", text="")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(cscene, "use_distance_cull")
|
||||
sub = col.column()
|
||||
row = layout.row(heading="Distance Culling")
|
||||
row.prop(cscene, "use_distance_cull", text="")
|
||||
sub = row.column()
|
||||
sub.active = cscene.use_distance_cull
|
||||
sub.prop(cscene, "distance_cull_margin", text="Distance")
|
||||
sub.prop(cscene, "distance_cull_margin", text="")
|
||||
|
||||
|
||||
class CYCLES_VIEW3D_PT_shading_render_pass(Panel):
|
||||
|
@@ -108,7 +108,7 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
}
|
||||
|
||||
if (dicing_prop_changed) {
|
||||
for (const pair<GeometryKey, Geometry *> &iter : geometry_map.key_to_scene_data()) {
|
||||
for (const pair<const GeometryKey, Geometry *> &iter : geometry_map.key_to_scene_data()) {
|
||||
Geometry *geom = iter.second;
|
||||
if (geom->type == Geometry::MESH) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
@@ -142,7 +142,7 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
BL::Object b_ob(b_id);
|
||||
const bool updated_geometry = b_update->is_updated_geometry();
|
||||
|
||||
if (b_update->is_updated_transform()) {
|
||||
if (b_update->is_updated_transform() || b_update->is_updated_shading()) {
|
||||
object_map.set_recalc(b_ob);
|
||||
light_map.set_recalc(b_ob);
|
||||
}
|
||||
|
@@ -156,6 +156,19 @@ void BVHOptiX::pack_tlas()
|
||||
PackedBVH &bvh_pack = geom->bvh->pack;
|
||||
int geom_prim_offset = geom->prim_offset;
|
||||
|
||||
// Merge visibility flags of all objects and fix object indices for non-instanced geometry
|
||||
int object_index = 0; // Unused for instanced geometry
|
||||
int object_visibility = 0;
|
||||
foreach (Object *ob, objects) {
|
||||
if (ob->geometry == geom) {
|
||||
object_visibility |= ob->visibility_for_tracing();
|
||||
if (!geom->is_instanced()) {
|
||||
object_index = ob->get_device_index();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge primitive, object and triangle indexes
|
||||
if (!bvh_pack.prim_index.empty()) {
|
||||
int *bvh_prim_type = &bvh_pack.prim_type[0];
|
||||
@@ -174,8 +187,8 @@ void BVHOptiX::pack_tlas()
|
||||
}
|
||||
|
||||
pack_prim_type[pack_offset] = bvh_prim_type[i];
|
||||
pack_prim_object[pack_offset] = 0; // Unused for instanced geometry
|
||||
pack_prim_visibility[pack_offset] = bvh_prim_visibility[i];
|
||||
pack_prim_object[pack_offset] = object_index;
|
||||
pack_prim_visibility[pack_offset] = bvh_prim_visibility[i] | object_visibility;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,27 +201,6 @@ void BVHOptiX::pack_tlas()
|
||||
pack_verts_offset += prim_tri_size;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge visibility flags of all objects and fix object indices for non-instanced geometry
|
||||
foreach (Object *ob, objects) {
|
||||
Geometry *const geom = ob->geometry;
|
||||
size_t num_primitives = 0;
|
||||
|
||||
if (geom->type == Geometry::MESH) {
|
||||
num_primitives = static_cast<Mesh *const>(geom)->num_triangles();
|
||||
}
|
||||
else if (geom->type == Geometry::HAIR) {
|
||||
num_primitives = static_cast<Hair *const>(geom)->num_segments();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_primitives; ++i) {
|
||||
if (!geom->is_instanced()) {
|
||||
assert(pack.prim_object[geom->optix_prim_offset + i] == 0);
|
||||
pack.prim_object[geom->optix_prim_offset + i] = ob->get_device_index();
|
||||
}
|
||||
pack.prim_visibility[geom->optix_prim_offset + i] |= ob->visibility_for_tracing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BVHOptiX::pack_nodes(const BVHNode *)
|
||||
|
@@ -71,6 +71,7 @@ __device__ half __float2half(const float f)
|
||||
#define ccl_may_alias
|
||||
#define ccl_addr_space
|
||||
#define ccl_restrict __restrict__
|
||||
#define ccl_loop_no_unroll
|
||||
/* TODO(sergey): In theory we might use references with CUDA, however
|
||||
* performance impact yet to be investigated.
|
||||
*/
|
||||
|
@@ -43,6 +43,7 @@
|
||||
#define ccl_local __local
|
||||
#define ccl_local_param __local
|
||||
#define ccl_private __private
|
||||
#define ccl_loop_no_unroll __attribute__((opencl_unroll_hint(1)))
|
||||
#define ccl_restrict restrict
|
||||
#define ccl_ref
|
||||
#define ccl_align(n) __attribute__((aligned(n)))
|
||||
|
@@ -70,6 +70,7 @@ __device__ half __float2half(const float f)
|
||||
#define ccl_private
|
||||
#define ccl_may_alias
|
||||
#define ccl_addr_space
|
||||
#define ccl_loop_no_unroll
|
||||
#define ccl_restrict __restrict__
|
||||
#define ccl_ref
|
||||
#define ccl_align(n) __align__(n)
|
||||
|
@@ -199,32 +199,33 @@ ccl_device float pmj_sample_1D(KernelGlobals *kg, int sample, int rng_hash, int
|
||||
{
|
||||
/* Fallback to random */
|
||||
if (sample >= NUM_PMJ_SAMPLES) {
|
||||
int p = rng_hash + dimension;
|
||||
const int p = rng_hash + dimension;
|
||||
return cmj_randfloat(sample, p);
|
||||
}
|
||||
uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
|
||||
int index = ((dimension % NUM_PMJ_PATTERNS) * NUM_PMJ_SAMPLES + sample) * 2;
|
||||
return __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index) ^ (tmp_rng & 0x007fffff)) -
|
||||
1.0f;
|
||||
else {
|
||||
const uint mask = cmj_hash_simple(dimension, rng_hash) & 0x007fffff;
|
||||
const int index = ((dimension % NUM_PMJ_PATTERNS) * NUM_PMJ_SAMPLES + sample) * 2;
|
||||
return __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index) ^ mask) - 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device void pmj_sample_2D(
|
||||
KernelGlobals *kg, int sample, int rng_hash, int dimension, float *fx, float *fy)
|
||||
ccl_device float2 pmj_sample_2D(KernelGlobals *kg, int sample, int rng_hash, int dimension)
|
||||
{
|
||||
if (sample >= NUM_PMJ_SAMPLES) {
|
||||
int p = rng_hash + dimension;
|
||||
*fx = cmj_randfloat(sample, p);
|
||||
*fy = cmj_randfloat(sample, p + 1);
|
||||
return;
|
||||
const int p = rng_hash + dimension;
|
||||
const float fx = cmj_randfloat(sample, p);
|
||||
const float fy = cmj_randfloat(sample, p + 1);
|
||||
return make_float2(fx, fy);
|
||||
}
|
||||
else {
|
||||
const int index = ((dimension % NUM_PMJ_PATTERNS) * NUM_PMJ_SAMPLES + sample) * 2;
|
||||
const uint maskx = cmj_hash_simple(dimension, rng_hash) & 0x007fffff;
|
||||
const uint masky = cmj_hash_simple(dimension + 1, rng_hash) & 0x007fffff;
|
||||
const float fx = __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index) ^ maskx) - 1.0f;
|
||||
const float fy = __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index + 1) ^ masky) -
|
||||
1.0f;
|
||||
return make_float2(fx, fy);
|
||||
}
|
||||
uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
|
||||
int index = ((dimension % NUM_PMJ_PATTERNS) * NUM_PMJ_SAMPLES + sample) * 2;
|
||||
*fx = __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index) ^ (tmp_rng & 0x007fffff)) -
|
||||
1.0f;
|
||||
tmp_rng = cmj_hash_simple(dimension + 1, rng_hash);
|
||||
*fy = __uint_as_float(kernel_tex_fetch(__sample_pattern_lut, index + 1) ^
|
||||
(tmp_rng & 0x007fffff)) -
|
||||
1.0f;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -102,7 +102,9 @@ ccl_device_forceinline void path_rng_2D(KernelGlobals *kg,
|
||||
return;
|
||||
#endif
|
||||
if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_PMJ) {
|
||||
pmj_sample_2D(kg, sample, rng_hash, dimension, fx, fy);
|
||||
const float2 f = pmj_sample_2D(kg, sample, rng_hash, dimension);
|
||||
*fx = f.x;
|
||||
*fy = f.y;
|
||||
return;
|
||||
}
|
||||
#ifdef __CMJ__
|
||||
|
@@ -1011,7 +1011,13 @@ bool OSLRenderServices::get_userdata(
|
||||
return false; /* disabled by lockgeom */
|
||||
}
|
||||
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring filename,
|
||||
OSL::ShadingContext *)
|
||||
#else
|
||||
|
||||
TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring filename)
|
||||
#endif
|
||||
{
|
||||
OSLTextureHandleMap::iterator it = textures.find(filename);
|
||||
|
||||
@@ -1365,6 +1371,17 @@ bool OSLRenderServices::environment(ustring filename,
|
||||
return status;
|
||||
}
|
||||
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
bool OSLRenderServices::get_texture_info(ustring filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *,
|
||||
OSL::ShadingContext *,
|
||||
int subimage,
|
||||
ustring dataname,
|
||||
TypeDesc datatype,
|
||||
void *data,
|
||||
ustring *)
|
||||
#else
|
||||
bool OSLRenderServices::get_texture_info(OSL::ShaderGlobals *sg,
|
||||
ustring filename,
|
||||
TextureHandle *texture_handle,
|
||||
@@ -1372,6 +1389,7 @@ bool OSLRenderServices::get_texture_info(OSL::ShaderGlobals *sg,
|
||||
ustring dataname,
|
||||
TypeDesc datatype,
|
||||
void *data)
|
||||
#endif
|
||||
{
|
||||
OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
|
||||
|
||||
|
@@ -173,7 +173,12 @@ class OSLRenderServices : public OSL::RendererServices {
|
||||
void *val,
|
||||
bool derivatives) override;
|
||||
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
TextureSystem::TextureHandle *get_texture_handle(ustring filename,
|
||||
OSL::ShadingContext *context) override;
|
||||
#else
|
||||
TextureSystem::TextureHandle *get_texture_handle(ustring filename) override;
|
||||
#endif
|
||||
|
||||
bool good(TextureSystem::TextureHandle *texture_handle) override;
|
||||
|
||||
@@ -224,6 +229,17 @@ class OSLRenderServices : public OSL::RendererServices {
|
||||
float *dresultdt,
|
||||
ustring *errormessage) override;
|
||||
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
bool get_texture_info(ustring filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
OSL::ShadingContext *shading_context,
|
||||
int subimage,
|
||||
ustring dataname,
|
||||
TypeDesc datatype,
|
||||
void *data,
|
||||
ustring *errormessage) override;
|
||||
#else
|
||||
bool get_texture_info(OSL::ShaderGlobals *sg,
|
||||
ustring filename,
|
||||
TextureHandle *texture_handle,
|
||||
@@ -231,6 +247,7 @@ class OSLRenderServices : public OSL::RendererServices {
|
||||
ustring dataname,
|
||||
TypeDesc datatype,
|
||||
void *data) override;
|
||||
#endif
|
||||
|
||||
static bool get_background_attribute(
|
||||
KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val);
|
||||
|
@@ -684,7 +684,8 @@ ccl_device void voronoi_f1_4d(float4 coord,
|
||||
float4 targetPosition = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
for (int u = -1; u <= 1; u++) {
|
||||
for (int k = -1; k <= 1; k++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
ccl_loop_no_unroll for (int j = -1; j <= 1; j++)
|
||||
{
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
float4 cellOffset = make_float4(i, j, k, u);
|
||||
float4 pointPosition = cellOffset +
|
||||
@@ -722,7 +723,8 @@ ccl_device void voronoi_smooth_f1_4d(float4 coord,
|
||||
float4 smoothPosition = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
for (int u = -2; u <= 2; u++) {
|
||||
for (int k = -2; k <= 2; k++) {
|
||||
for (int j = -2; j <= 2; j++) {
|
||||
ccl_loop_no_unroll for (int j = -2; j <= 2; j++)
|
||||
{
|
||||
for (int i = -2; i <= 2; i++) {
|
||||
float4 cellOffset = make_float4(i, j, k, u);
|
||||
float4 pointPosition = cellOffset +
|
||||
@@ -765,7 +767,8 @@ ccl_device void voronoi_f2_4d(float4 coord,
|
||||
float4 positionF2 = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
for (int u = -1; u <= 1; u++) {
|
||||
for (int k = -1; k <= 1; k++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
ccl_loop_no_unroll for (int j = -1; j <= 1; j++)
|
||||
{
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
float4 cellOffset = make_float4(i, j, k, u);
|
||||
float4 pointPosition = cellOffset +
|
||||
@@ -803,7 +806,8 @@ ccl_device void voronoi_distance_to_edge_4d(float4 coord, float randomness, floa
|
||||
float minDistance = 8.0f;
|
||||
for (int u = -1; u <= 1; u++) {
|
||||
for (int k = -1; k <= 1; k++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
ccl_loop_no_unroll for (int j = -1; j <= 1; j++)
|
||||
{
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
float4 cellOffset = make_float4(i, j, k, u);
|
||||
float4 vectorToPoint = cellOffset +
|
||||
@@ -822,7 +826,8 @@ ccl_device void voronoi_distance_to_edge_4d(float4 coord, float randomness, floa
|
||||
minDistance = 8.0f;
|
||||
for (int u = -1; u <= 1; u++) {
|
||||
for (int k = -1; k <= 1; k++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
ccl_loop_no_unroll for (int j = -1; j <= 1; j++)
|
||||
{
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
float4 cellOffset = make_float4(i, j, k, u);
|
||||
float4 vectorToPoint = cellOffset +
|
||||
@@ -851,7 +856,8 @@ ccl_device void voronoi_n_sphere_radius_4d(float4 coord, float randomness, float
|
||||
float minDistance = 8.0f;
|
||||
for (int u = -1; u <= 1; u++) {
|
||||
for (int k = -1; k <= 1; k++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
ccl_loop_no_unroll for (int j = -1; j <= 1; j++)
|
||||
{
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
float4 cellOffset = make_float4(i, j, k, u);
|
||||
float4 pointPosition = cellOffset +
|
||||
@@ -871,7 +877,8 @@ ccl_device void voronoi_n_sphere_radius_4d(float4 coord, float randomness, float
|
||||
float4 closestPointToClosestPoint = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
for (int u = -1; u <= 1; u++) {
|
||||
for (int k = -1; k <= 1; k++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
ccl_loop_no_unroll for (int j = -1; j <= 1; j++)
|
||||
{
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
if (i == 0 && j == 0 && k == 0 && u == 0) {
|
||||
continue;
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include "render/scene.h"
|
||||
|
||||
#include "util/util_foreach.h"
|
||||
#include "util/util_hash.h"
|
||||
#include "util/util_logging.h"
|
||||
#include "util/util_progress.h"
|
||||
#include "util/util_types.h"
|
||||
@@ -447,7 +448,14 @@ void GeometryManager::create_volume_mesh(Mesh *mesh, Progress &progress)
|
||||
start_point = transform_point(&itfm, start_point);
|
||||
cell_size = transform_direction(&itfm, cell_size);
|
||||
|
||||
volume_params.start_point = start_point;
|
||||
/* Slightly offset vertex coordinates to avoid overlapping faces with other
|
||||
* volumes or meshes. The proper solution would be to improve intersection in
|
||||
* the kernel to support robust handling of multiple overlapping faces or use
|
||||
* an all-hit intersection similar to shadows. */
|
||||
const float3 face_overlap_avoidance = cell_size * 0.1f *
|
||||
hash_uint_to_float(hash_string(mesh->name.c_str()));
|
||||
|
||||
volume_params.start_point = start_point + face_overlap_avoidance;
|
||||
volume_params.cell_size = cell_size;
|
||||
volume_params.pad_size = pad_size;
|
||||
|
||||
|
@@ -293,14 +293,12 @@ void Session::run_gpu()
|
||||
* reset and draw in between */
|
||||
thread_scoped_lock buffers_lock(buffers_mutex);
|
||||
|
||||
/* avoid excessive denoising in viewport after reaching a certain amount of samples */
|
||||
bool need_denoise = tile_manager.schedule_denoising || tile_manager.state.sample < 20 ||
|
||||
(time_dt() - last_display_time) >= params.progressive_update_timeout;
|
||||
|
||||
/* update status and timing */
|
||||
update_status_time();
|
||||
|
||||
/* render */
|
||||
bool delayed_denoise = false;
|
||||
const bool need_denoise = render_need_denoise(delayed_denoise);
|
||||
render(need_denoise);
|
||||
|
||||
device->task_wait();
|
||||
@@ -311,7 +309,7 @@ void Session::run_gpu()
|
||||
/* update status and timing */
|
||||
update_status_time();
|
||||
|
||||
gpu_need_display_buffer_update = need_denoise || !params.run_denoising;
|
||||
gpu_need_display_buffer_update = !delayed_denoise;
|
||||
gpu_draw_ready = true;
|
||||
progress.set_update();
|
||||
|
||||
@@ -477,7 +475,7 @@ void Session::update_tile_sample(RenderTile &rtile)
|
||||
update_status_time();
|
||||
}
|
||||
|
||||
void Session::release_tile(RenderTile &rtile)
|
||||
void Session::release_tile(RenderTile &rtile, const bool need_denoise)
|
||||
{
|
||||
thread_scoped_lock tile_lock(tile_mutex);
|
||||
|
||||
@@ -485,7 +483,7 @@ void Session::release_tile(RenderTile &rtile)
|
||||
|
||||
bool delete_tile;
|
||||
|
||||
if (tile_manager.finish_tile(rtile.tile_index, delete_tile)) {
|
||||
if (tile_manager.finish_tile(rtile.tile_index, need_denoise, delete_tile)) {
|
||||
if (write_render_tile_cb && params.progressive_refine == false) {
|
||||
write_render_tile_cb(rtile);
|
||||
}
|
||||
@@ -687,21 +685,19 @@ void Session::run_cpu()
|
||||
* reset and draw in between */
|
||||
thread_scoped_lock buffers_lock(buffers_mutex);
|
||||
|
||||
/* avoid excessive denoising in viewport after reaching a certain amount of samples */
|
||||
bool need_denoise = tile_manager.schedule_denoising || tile_manager.state.sample < 20 ||
|
||||
(time_dt() - last_display_time) >= params.progressive_update_timeout;
|
||||
|
||||
/* update status and timing */
|
||||
update_status_time();
|
||||
|
||||
/* render */
|
||||
bool delayed_denoise = false;
|
||||
const bool need_denoise = render_need_denoise(delayed_denoise);
|
||||
render(need_denoise);
|
||||
|
||||
/* update status and timing */
|
||||
update_status_time();
|
||||
|
||||
if (!params.background)
|
||||
need_copy_to_display_buffer = need_denoise || !params.run_denoising;
|
||||
need_copy_to_display_buffer = !delayed_denoise;
|
||||
|
||||
if (!device->error_message().empty())
|
||||
progress.set_error(device->error_message());
|
||||
@@ -1083,7 +1079,46 @@ void Session::update_status_time(bool show_pause, bool show_done)
|
||||
progress.set_status(status, substatus);
|
||||
}
|
||||
|
||||
void Session::render(bool with_denoising)
|
||||
bool Session::render_need_denoise(bool &delayed)
|
||||
{
|
||||
delayed = false;
|
||||
|
||||
/* Denoising enabled? */
|
||||
if (!params.run_denoising) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params.background) {
|
||||
/* Background render, only denoise when rendering the last sample. */
|
||||
return tile_manager.done();
|
||||
}
|
||||
|
||||
/* Viewport render. */
|
||||
|
||||
/* It can happen that denoising was already enabled, but the scene still needs an update. */
|
||||
if (scene->film->need_update || !scene->film->denoising_data_offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Do not denoise until the sample at which denoising should start is reached. */
|
||||
if (tile_manager.state.sample < params.denoising_start_sample) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Cannot denoise with resolution divider and separate denoising devices.
|
||||
* It breaks the copy in 'MultiDevice::map_neighbor_tiles' (which operates on
|
||||
* the full buffer dimensions and not the scaled ones). */
|
||||
if (!params.device.denoising_devices.empty() && tile_manager.state.resolution_divider > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Avoid excessive denoising in viewport after reaching a certain amount of samples. */
|
||||
delayed = (tile_manager.state.sample >= 20 &&
|
||||
(time_dt() - last_display_time) < params.progressive_update_timeout);
|
||||
return !delayed;
|
||||
}
|
||||
|
||||
void Session::render(bool need_denoise)
|
||||
{
|
||||
if (buffers && tile_manager.state.sample == tile_manager.range_start_sample) {
|
||||
/* Clear buffers. */
|
||||
@@ -1098,7 +1133,7 @@ void Session::render(bool with_denoising)
|
||||
DeviceTask task(DeviceTask::RENDER);
|
||||
|
||||
task.acquire_tile = function_bind(&Session::acquire_tile, this, _2, _1, _3);
|
||||
task.release_tile = function_bind(&Session::release_tile, this, _1);
|
||||
task.release_tile = function_bind(&Session::release_tile, this, _1, need_denoise);
|
||||
task.map_neighbor_tiles = function_bind(&Session::map_neighbor_tiles, this, _1, _2);
|
||||
task.unmap_neighbor_tiles = function_bind(&Session::unmap_neighbor_tiles, this, _1, _2);
|
||||
task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
|
||||
@@ -1115,27 +1150,7 @@ void Session::render(bool with_denoising)
|
||||
/* Acquire render tiles by default. */
|
||||
task.tile_types = RenderTile::PATH_TRACE;
|
||||
|
||||
with_denoising = params.run_denoising && with_denoising;
|
||||
if (with_denoising) {
|
||||
/* Do not denoise viewport until the sample at which denoising should start is reached. */
|
||||
if (!params.background && tile_manager.state.sample < params.denoising_start_sample) {
|
||||
with_denoising = false;
|
||||
}
|
||||
|
||||
/* Cannot denoise with resolution divider and separate denoising devices.
|
||||
* It breaks the copy in 'MultiDevice::map_neighbor_tiles' (which operates on the full buffer
|
||||
* dimensions and not the scaled ones). */
|
||||
if (!params.device.denoising_devices.empty() && tile_manager.state.resolution_divider > 1) {
|
||||
with_denoising = false;
|
||||
}
|
||||
|
||||
/* It can happen that denoising was already enabled, but the scene still needs an update. */
|
||||
if (scene->film->need_update || !scene->film->denoising_data_offset) {
|
||||
with_denoising = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (with_denoising) {
|
||||
if (need_denoise) {
|
||||
task.denoising = params.denoising;
|
||||
|
||||
task.pass_stride = scene->film->pass_stride;
|
||||
|
@@ -186,7 +186,7 @@ class Session {
|
||||
|
||||
void update_status_time(bool show_pause = false, bool show_done = false);
|
||||
|
||||
void render(bool with_denoising);
|
||||
void render(bool use_denoise);
|
||||
void copy_to_display_buffer(int sample);
|
||||
|
||||
void reset_(BufferParams ¶ms, int samples);
|
||||
@@ -199,9 +199,11 @@ class Session {
|
||||
bool draw_gpu(BufferParams ¶ms, DeviceDrawParams &draw_params);
|
||||
void reset_gpu(BufferParams ¶ms, int samples);
|
||||
|
||||
bool render_need_denoise(bool &delayed);
|
||||
|
||||
bool acquire_tile(RenderTile &tile, Device *tile_device, uint tile_types);
|
||||
void update_tile_sample(RenderTile &tile);
|
||||
void release_tile(RenderTile &tile);
|
||||
void release_tile(RenderTile &tile, const bool need_denoise);
|
||||
|
||||
void map_neighbor_tiles(RenderTile *tiles, Device *tile_device);
|
||||
void unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device);
|
||||
|
@@ -441,13 +441,13 @@ bool TileManager::check_neighbor_state(int index, Tile::State min_state)
|
||||
|
||||
/* Returns whether the tile should be written (and freed if no denoising is used) instead of
|
||||
* updating. */
|
||||
bool TileManager::finish_tile(int index, bool &delete_tile)
|
||||
bool TileManager::finish_tile(const int index, const bool need_denoise, bool &delete_tile)
|
||||
{
|
||||
delete_tile = false;
|
||||
|
||||
switch (state.tiles[index].state) {
|
||||
case Tile::RENDER: {
|
||||
if (!schedule_denoising) {
|
||||
if (!(schedule_denoising && need_denoise)) {
|
||||
state.tiles[index].state = Tile::DONE;
|
||||
delete_tile = !progressive;
|
||||
return true;
|
||||
|
@@ -107,7 +107,7 @@ class TileManager {
|
||||
void set_samples(int num_samples);
|
||||
bool next();
|
||||
bool next_tile(Tile *&tile, int device, uint tile_types);
|
||||
bool finish_tile(int index, bool &delete_tile);
|
||||
bool finish_tile(const int index, const bool need_denoise, bool &delete_tile);
|
||||
bool done();
|
||||
bool has_tiles();
|
||||
|
||||
|
@@ -57,7 +57,7 @@ struct avxb {
|
||||
: m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a), b, 1))
|
||||
{
|
||||
}
|
||||
__forceinline operator const __m256 &(void)const
|
||||
__forceinline operator const __m256 &(void) const
|
||||
{
|
||||
return m256;
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ struct avxi {
|
||||
__forceinline avxi(const __m256i a) : m256(a)
|
||||
{
|
||||
}
|
||||
__forceinline operator const __m256i &(void)const
|
||||
__forceinline operator const __m256i &(void) const
|
||||
{
|
||||
return m256;
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@
|
||||
# define ccl_restrict __restrict
|
||||
# define ccl_ref &
|
||||
# define ccl_optional_struct_init
|
||||
# define ccl_loop_no_unroll
|
||||
# define __KERNEL_WITH_SSE_ALIGN__
|
||||
|
||||
# if defined(_WIN32) && !defined(FREE_WINDOWS)
|
||||
|
@@ -57,7 +57,7 @@ struct sseb {
|
||||
__forceinline sseb(const __m128 input) : m128(input)
|
||||
{
|
||||
}
|
||||
__forceinline operator const __m128 &(void)const
|
||||
__forceinline operator const __m128 &(void) const
|
||||
{
|
||||
return m128;
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ struct ssei {
|
||||
__forceinline ssei(const __m128i a) : m128(a)
|
||||
{
|
||||
}
|
||||
__forceinline operator const __m128i &(void)const
|
||||
__forceinline operator const __m128i &(void) const
|
||||
{
|
||||
return m128;
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ typedef float (*DualConCo)[3];
|
||||
|
||||
typedef unsigned int (*DualConTri)[3];
|
||||
|
||||
typedef unsigned int(*DualConLoop);
|
||||
typedef unsigned int *DualConLoop;
|
||||
|
||||
typedef struct DualConInput {
|
||||
DualConLoop mloop;
|
||||
|
@@ -480,7 +480,7 @@ void Octree::trace()
|
||||
if (chdpath != NULL) {
|
||||
dc_printf("there are incomplete rings.\n");
|
||||
printPaths(chdpath);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *&paths)
|
||||
|
@@ -21,7 +21,6 @@
|
||||
set(INC
|
||||
.
|
||||
../glew-mx
|
||||
../string
|
||||
../../source/blender/imbuf
|
||||
../../source/blender/makesdna
|
||||
)
|
||||
@@ -86,7 +85,6 @@ set(SRC
|
||||
|
||||
set(LIB
|
||||
bf_intern_glew_mx
|
||||
bf_intern_string
|
||||
${GLEW_LIBRARY}
|
||||
)
|
||||
|
||||
@@ -151,7 +149,7 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
elseif(APPLE AND NOT WITH_X11)
|
||||
elseif(APPLE AND NOT WITH_GHOST_X11)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DisplayManagerCocoa.mm
|
||||
intern/GHOST_SystemCocoa.mm
|
||||
@@ -179,73 +177,143 @@ elseif(APPLE AND NOT WITH_X11)
|
||||
)
|
||||
endif()
|
||||
|
||||
elseif(WITH_X11)
|
||||
list(APPEND INC_SYS
|
||||
${X11_X11_INCLUDE_PATH}
|
||||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DisplayManagerX11.cpp
|
||||
intern/GHOST_SystemX11.cpp
|
||||
intern/GHOST_TaskbarX11.cpp
|
||||
intern/GHOST_WindowX11.cpp
|
||||
|
||||
intern/GHOST_DisplayManagerX11.h
|
||||
intern/GHOST_IconX11.h
|
||||
intern/GHOST_SystemX11.h
|
||||
intern/GHOST_TaskbarX11.h
|
||||
intern/GHOST_WindowX11.h
|
||||
)
|
||||
|
||||
if(NOT WITH_GL_EGL)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ContextGLX.cpp
|
||||
|
||||
intern/GHOST_ContextGLX.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_XDND)
|
||||
add_definitions(-DWITH_XDND)
|
||||
|
||||
list(APPEND LIB
|
||||
extern_xdnd
|
||||
)
|
||||
|
||||
list(APPEND INC
|
||||
../../extern/xdnd
|
||||
elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
||||
if(WITH_GHOST_X11)
|
||||
list(APPEND INC_SYS
|
||||
${X11_X11_INCLUDE_PATH}
|
||||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DropTargetX11.cpp
|
||||
intern/GHOST_DisplayManagerX11.cpp
|
||||
intern/GHOST_SystemX11.cpp
|
||||
intern/GHOST_TaskbarX11.cpp
|
||||
intern/GHOST_WindowX11.cpp
|
||||
|
||||
intern/GHOST_DropTargetX11.h
|
||||
intern/GHOST_DisplayManagerX11.h
|
||||
intern/GHOST_IconX11.h
|
||||
intern/GHOST_SystemX11.h
|
||||
intern/GHOST_TaskbarX11.h
|
||||
intern/GHOST_WindowX11.h
|
||||
)
|
||||
|
||||
if(NOT WITH_GL_EGL)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ContextGLX.cpp
|
||||
|
||||
intern/GHOST_ContextGLX.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_XDND)
|
||||
add_definitions(-DWITH_XDND)
|
||||
|
||||
list(APPEND LIB
|
||||
extern_xdnd
|
||||
)
|
||||
|
||||
list(APPEND INC
|
||||
../../extern/xdnd
|
||||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DropTargetX11.cpp
|
||||
|
||||
intern/GHOST_DropTargetX11.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(X11_XF86keysym_INCLUDE_PATH)
|
||||
add_definitions(-DWITH_XF86KEYSYM)
|
||||
list(APPEND INC_SYS
|
||||
${X11_XF86keysym_INCLUDE_PATH}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_X11_XF86VMODE)
|
||||
add_definitions(-DWITH_X11_XF86VMODE)
|
||||
list(APPEND INC_SYS
|
||||
${X11_xf86vmode_INCLUDE_PATH}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_X11_XFIXES)
|
||||
add_definitions(-DWITH_X11_XFIXES)
|
||||
list(APPEND INC_SYS
|
||||
${X11_Xfixes_INCLUDE_PATH}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_X11_ALPHA)
|
||||
add_definitions(-DWITH_X11_ALPHA)
|
||||
endif()
|
||||
|
||||
if(WITH_X11_XINPUT)
|
||||
add_definitions(-DWITH_X11_XINPUT)
|
||||
list(APPEND INC_SYS
|
||||
${X11_Xinput_INCLUDE_PATH}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_definitions(-DWITH_GHOST_X11)
|
||||
endif()
|
||||
|
||||
if(X11_XF86keysym_INCLUDE_PATH)
|
||||
add_definitions(-DWITH_XF86KEYSYM)
|
||||
if(WITH_GHOST_WAYLAND)
|
||||
list(APPEND INC_SYS
|
||||
${X11_XF86keysym_INCLUDE_PATH}
|
||||
${wayland-client_INCLUDE_DIRS}
|
||||
${wayland-egl_INCLUDE_DIRS}
|
||||
${xkbcommon_INCLUDE_DIRS}
|
||||
${wayland-cursor_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_X11_XF86VMODE)
|
||||
add_definitions(-DWITH_X11_XF86VMODE)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_SystemWayland.cpp
|
||||
intern/GHOST_WindowWayland.cpp
|
||||
|
||||
intern/GHOST_SystemWayland.h
|
||||
intern/GHOST_WindowWayland.h
|
||||
)
|
||||
|
||||
pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
|
||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||
|
||||
# Generate protocols bindings.
|
||||
macro(generate_protocol_bindings NAME PROT_DEF)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h
|
||||
COMMAND ${WAYLAND_SCANNER} client-header ${PROT_DEF} ${NAME}-client-protocol.h
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c
|
||||
COMMAND ${WAYLAND_SCANNER} private-code ${PROT_DEF} ${NAME}-client-protocol.c
|
||||
DEPENDS ${NAME}-client-protocol.h
|
||||
)
|
||||
list(APPEND SRC
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${NAME}-client-protocol.h
|
||||
)
|
||||
endmacro()
|
||||
|
||||
list(APPEND INC_SYS
|
||||
${X11_xf86vmode_INCLUDE_PATH}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_X11_XFIXES)
|
||||
add_definitions(-DWITH_X11_XFIXES)
|
||||
list(APPEND INC_SYS
|
||||
${X11_Xfixes_INCLUDE_PATH}
|
||||
# xdg-shell.
|
||||
generate_protocol_bindings(
|
||||
xdg-shell
|
||||
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
||||
)
|
||||
# Pointer-constraints.
|
||||
generate_protocol_bindings(
|
||||
pointer-constraints
|
||||
"${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
|
||||
)
|
||||
# Relative-pointer.
|
||||
generate_protocol_bindings(
|
||||
relative-pointer
|
||||
"${WAYLAND_PROTOCOLS_DIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_X11_ALPHA)
|
||||
add_definitions(-DWITH_X11_ALPHA)
|
||||
add_definitions(-DWITH_GHOST_WAYLAND)
|
||||
endif()
|
||||
|
||||
if(WITH_INPUT_NDOF)
|
||||
@@ -260,14 +328,6 @@ elseif(WITH_X11)
|
||||
add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}")
|
||||
endif()
|
||||
|
||||
if(WITH_X11_XINPUT)
|
||||
add_definitions(-DWITH_X11_XINPUT)
|
||||
list(APPEND INC_SYS
|
||||
${X11_Xinput_INCLUDE_PATH}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_definitions(-DWITH_X11)
|
||||
|
||||
elseif(WIN32)
|
||||
# # Warnings as errors, this is too strict!
|
||||
|
@@ -26,7 +26,6 @@
|
||||
#define __GHOST_IContext_H__
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
#include "STR_String.h"
|
||||
|
||||
/**
|
||||
* Interface for GHOST context.
|
||||
|
@@ -27,6 +27,8 @@
|
||||
#ifndef __GHOST_ISYSTEM_H__
|
||||
#define __GHOST_ISYSTEM_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "GHOST_IContext.h"
|
||||
#include "GHOST_ITimerTask.h"
|
||||
#include "GHOST_IWindow.h"
|
||||
@@ -240,7 +242,7 @@ class GHOST_ISystem {
|
||||
* \param parentWindow: Parent (embedder) window
|
||||
* \return The new window (or 0 if creation failed).
|
||||
*/
|
||||
virtual GHOST_IWindow *createWindow(const STR_String &title,
|
||||
virtual GHOST_IWindow *createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
|
@@ -27,7 +27,9 @@
|
||||
|
||||
#include "GHOST_Rect.h"
|
||||
#include "GHOST_Types.h"
|
||||
#include "STR_String.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* Interface for GHOST windows.
|
||||
@@ -81,13 +83,13 @@ class GHOST_IWindow {
|
||||
* Sets the title displayed in the title bar.
|
||||
* \param title The title to display in the title bar.
|
||||
*/
|
||||
virtual void setTitle(const STR_String &title) = 0;
|
||||
virtual void setTitle(const char *title) = 0;
|
||||
|
||||
/**
|
||||
* Returns the title displayed in the title bar.
|
||||
* \param title The title displayed in the title bar.
|
||||
*/
|
||||
virtual void getTitle(STR_String &title) const = 0;
|
||||
virtual std::string getTitle() const = 0;
|
||||
|
||||
/**
|
||||
* Returns the window rectangle dimensions.
|
||||
|
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
#include "GHOST_IEvent.h"
|
||||
@@ -527,17 +528,15 @@ void GHOST_SetTitle(GHOST_WindowHandle windowhandle, const char *title)
|
||||
char *GHOST_GetTitle(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||
STR_String title;
|
||||
std::string title = window->getTitle();
|
||||
|
||||
window->getTitle(title);
|
||||
|
||||
char *ctitle = (char *)malloc(title.Length() + 1);
|
||||
char *ctitle = (char *)malloc(title.size() + 1);
|
||||
|
||||
if (ctitle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(ctitle, title.Ptr());
|
||||
strcpy(ctitle, title.c_str());
|
||||
|
||||
return ctitle;
|
||||
}
|
||||
@@ -678,7 +677,7 @@ GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
|
||||
return context->activateDrawingContext();
|
||||
}
|
||||
else {
|
||||
GHOST_PRINT("GHOST_ActivateOpenGLContext: Context not valid");
|
||||
GHOST_PRINTF("%s: Context not valid\n", __func__);
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
@@ -33,15 +33,11 @@
|
||||
#endif
|
||||
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
# define GHOST_DEBUG // spit ghost events to stdout
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
# include <iostream>
|
||||
# include <stdio.h> //for printf()
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
# define GHOST_PRINT(x) \
|
||||
{ \
|
||||
std::cout << x; \
|
||||
@@ -52,10 +48,10 @@
|
||||
printf(x, __VA_ARGS__); \
|
||||
} \
|
||||
(void)0
|
||||
#else // GHOST_DEBUG
|
||||
#else // WITH_GHOST_DEBUG
|
||||
# define GHOST_PRINT(x)
|
||||
# define GHOST_PRINTF(x, ...)
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
||||
#ifdef WITH_ASSERT_ABORT
|
||||
# include <stdio.h> //for fprintf()
|
||||
@@ -70,7 +66,7 @@
|
||||
} \
|
||||
} \
|
||||
(void)0
|
||||
#elif defined(GHOST_DEBUG)
|
||||
#elif defined(WITH_GHOST_DEBUG)
|
||||
# define GHOST_ASSERT(x, info) \
|
||||
{ \
|
||||
if (!(x)) { \
|
||||
@@ -80,8 +76,8 @@
|
||||
} \
|
||||
} \
|
||||
(void)0
|
||||
#else // GHOST_DEBUG
|
||||
#else // WITH_GHOST_DEBUG
|
||||
# define GHOST_ASSERT(x, info) ((void)0)
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
||||
#endif // __GHOST_DEBUG_H__
|
||||
|
@@ -80,13 +80,13 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display,
|
||||
GHOST_TSuccess success;
|
||||
DEVMODE dm;
|
||||
if (::EnumDisplaySettings(display_device.DeviceName, index, &dm)) {
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n",
|
||||
dm.dmPelsWidth,
|
||||
dm.dmPelsHeight,
|
||||
dm.dmBitsPerPel,
|
||||
dm.dmDisplayFrequency);
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
setting.xPixels = dm.dmPelsWidth;
|
||||
setting.yPixels = dm.dmPelsHeight;
|
||||
setting.bpp = dm.dmBitsPerPel;
|
||||
@@ -142,16 +142,16 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(
|
||||
* dm.dmSize = sizeof(DEVMODE);
|
||||
* dm.dmDriverExtra = 0;
|
||||
*/
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
printf("display change: Requested settings:\n");
|
||||
printf(" dmBitsPerPel=%d\n", dm.dmBitsPerPel);
|
||||
printf(" dmPelsWidth=%d\n", dm.dmPelsWidth);
|
||||
printf(" dmPelsHeight=%d\n", dm.dmPelsHeight);
|
||||
printf(" dmDisplayFrequency=%d\n", dm.dmDisplayFrequency);
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
||||
LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
switch (status) {
|
||||
case DISP_CHANGE_SUCCESSFUL:
|
||||
printf("display change: The settings change was successful.\n");
|
||||
@@ -182,6 +182,6 @@ GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(
|
||||
printf("display change: Return value invalid\n");
|
||||
break;
|
||||
}
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
return status == DISP_CHANGE_SUCCESSFUL ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
@@ -28,10 +28,10 @@
|
||||
#include "utf_winfunc.h"
|
||||
#include "utfconv.h"
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
// utility
|
||||
void printLastError(void);
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
||||
GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_SystemWin32 *system)
|
||||
: m_window(window), m_system(system)
|
||||
@@ -209,9 +209,9 @@ void *GHOST_DropTargetWin32::getGhostData(IDataObject *pDataObject)
|
||||
// return getDropDataAsBitmap(pDataObject);
|
||||
break;
|
||||
default:
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
::printf("\nGHOST_kDragnDropTypeUnknown");
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
@@ -284,10 +284,10 @@ void *GHOST_DropTargetWin32::getDropDataAsString(IDataObject *pDataObject)
|
||||
// Free memory
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
::ReleaseStgMedium(&stgmed);
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
::printf("\n<converted droped unicode string>\n%s\n</droped converted unicode string>\n",
|
||||
tmp_string);
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
return tmp_string;
|
||||
}
|
||||
}
|
||||
@@ -336,9 +336,9 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out)
|
||||
NULL);
|
||||
|
||||
if (!size) {
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
::printLastError();
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -351,16 +351,16 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char *&out)
|
||||
size = ::WideCharToMultiByte(CP_ACP, 0x00000400, in, -1, (LPSTR)out, size, NULL, NULL);
|
||||
|
||||
if (!size) {
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
::printLastError();
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
::free(out);
|
||||
out = NULL;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
void printLastError(void)
|
||||
{
|
||||
LPTSTR s;
|
||||
@@ -378,4 +378,4 @@ void printLastError(void)
|
||||
LocalFree(s);
|
||||
}
|
||||
}
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#ifndef __GHOST_EVENTKEY_H__
|
||||
#define __GHOST_EVENTKEY_H__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
/**
|
||||
|
@@ -27,8 +27,6 @@
|
||||
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
|
||||
#include "STR_String.h"
|
||||
|
||||
/**
|
||||
* An Event consumer that prints all the events to standard out.
|
||||
* Really useful when debugging.
|
||||
|
@@ -27,20 +27,22 @@
|
||||
|
||||
#include "GHOST_ISystem.h"
|
||||
|
||||
#ifdef WITH_X11
|
||||
#if defined(WITH_HEADLESS)
|
||||
# include "GHOST_SystemNULL.h"
|
||||
#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
|
||||
# include "GHOST_SystemWayland.h"
|
||||
# include "GHOST_SystemX11.h"
|
||||
#else
|
||||
# ifdef WITH_HEADLESS
|
||||
# include "GHOST_SystemNULL.h"
|
||||
# elif defined(WITH_GHOST_SDL)
|
||||
# include "GHOST_SystemSDL.h"
|
||||
# elif defined(WIN32)
|
||||
# include "GHOST_SystemWin32.h"
|
||||
# else
|
||||
# ifdef __APPLE__
|
||||
# include "GHOST_SystemCocoa.h"
|
||||
# endif
|
||||
# endif
|
||||
# include <stdexcept>
|
||||
#elif defined(WITH_GHOST_X11)
|
||||
# include "GHOST_SystemX11.h"
|
||||
#elif defined(WITH_GHOST_WAYLAND)
|
||||
# include "GHOST_SystemWayland.h"
|
||||
#elif defined(WITH_GHOST_SDL)
|
||||
# include "GHOST_SystemSDL.h"
|
||||
#elif defined(WIN32)
|
||||
# include "GHOST_SystemWin32.h"
|
||||
#elif defined(__APPLE__)
|
||||
# include "GHOST_SystemCocoa.h"
|
||||
#endif
|
||||
|
||||
GHOST_ISystem *GHOST_ISystem::m_system = NULL;
|
||||
@@ -49,20 +51,29 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (!m_system) {
|
||||
#ifdef WITH_X11
|
||||
m_system = new GHOST_SystemX11();
|
||||
#else
|
||||
# ifdef WITH_HEADLESS
|
||||
#if defined(WITH_HEADLESS)
|
||||
m_system = new GHOST_SystemNULL();
|
||||
# elif defined(WITH_GHOST_SDL)
|
||||
#elif defined(WITH_GHOST_X11) && defined(WITH_GHOST_WAYLAND)
|
||||
/* Special case, try Wayland, fall back to X11. */
|
||||
try {
|
||||
m_system = new GHOST_SystemWayland();
|
||||
}
|
||||
catch (const std::runtime_error &) {
|
||||
/* fallback to X11. */
|
||||
}
|
||||
if (!m_system) {
|
||||
m_system = new GHOST_SystemX11();
|
||||
}
|
||||
#elif defined(WITH_GHOST_X11)
|
||||
m_system = new GHOST_SystemX11();
|
||||
#elif defined(WITH_GHOST_WAYLAND)
|
||||
m_system = new GHOST_SystemWayland();
|
||||
#elif defined(WITH_GHOST_SDL)
|
||||
m_system = new GHOST_SystemSDL();
|
||||
# elif defined(WIN32)
|
||||
#elif defined(WIN32)
|
||||
m_system = new GHOST_SystemWin32();
|
||||
# else
|
||||
# ifdef __APPLE__
|
||||
#elif defined(__APPLE__)
|
||||
m_system = new GHOST_SystemCocoa();
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
success = m_system != NULL ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ class GHOST_IXrGraphicsBinding {
|
||||
|
||||
public:
|
||||
union {
|
||||
#if defined(WITH_X11)
|
||||
#if defined(WITH_GHOST_X11)
|
||||
XrGraphicsBindingOpenGLXlibKHR glx;
|
||||
#elif defined(WIN32)
|
||||
XrGraphicsBindingOpenGLWin32KHR wgl;
|
||||
|
@@ -19,6 +19,8 @@
|
||||
#include "GHOST_EventKey.h"
|
||||
#include "GHOST_EventNDOF.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h> // for error/info reporting
|
||||
#include <string.h> // for memory functions
|
||||
|
@@ -309,12 +309,12 @@ GHOST_TSuccess GHOST_System::init()
|
||||
m_windowManager = new GHOST_WindowManager();
|
||||
m_eventManager = new GHOST_EventManager();
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
if (m_eventManager) {
|
||||
m_eventPrinter = new GHOST_EventPrinter();
|
||||
m_eventManager->addConsumer(m_eventPrinter);
|
||||
}
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
||||
if (m_timerManager && m_windowManager && m_eventManager) {
|
||||
return GHOST_kSuccess;
|
||||
@@ -367,7 +367,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window,
|
||||
GHOST_ASSERT(m_displayManager,
|
||||
"GHOST_System::createFullScreenWindow(): invalid display manager");
|
||||
// GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
|
||||
*window = (GHOST_Window *)createWindow(STR_String(""),
|
||||
*window = (GHOST_Window *)createWindow("",
|
||||
0,
|
||||
0,
|
||||
settings.xPixels,
|
||||
|
@@ -31,9 +31,9 @@
|
||||
#include "GHOST_Debug.h"
|
||||
#include "GHOST_EventManager.h"
|
||||
#include "GHOST_ModifierKeys.h"
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
# include "GHOST_EventPrinter.h"
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
||||
class GHOST_DisplayManager;
|
||||
class GHOST_Event;
|
||||
@@ -238,7 +238,7 @@ class GHOST_System : public GHOST_ISystem {
|
||||
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
|
||||
* \param api Enum indicating which API to use.
|
||||
*/
|
||||
virtual void setTabletAPI(GHOST_TTabletAPI api);
|
||||
void setTabletAPI(GHOST_TTabletAPI api);
|
||||
GHOST_TTabletAPI getTabletAPI(void);
|
||||
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
@@ -390,9 +390,9 @@ class GHOST_System : public GHOST_ISystem {
|
||||
#endif
|
||||
|
||||
/** Prints all the events. */
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
GHOST_EventPrinter *m_eventPrinter;
|
||||
#endif // GHOST_DEBUG
|
||||
#endif // WITH_GHOST_DEBUG
|
||||
|
||||
/** Settings of the display before the display went fullscreen. */
|
||||
GHOST_DisplaySetting m_preFullScreenSetting;
|
||||
|
@@ -100,7 +100,7 @@ class GHOST_SystemCocoa : public GHOST_System {
|
||||
* \param parentWindow Parent (embedder) window
|
||||
* \return The new window (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IWindow *createWindow(const STR_String &title,
|
||||
GHOST_IWindow *createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
|
@@ -698,7 +698,7 @@ void GHOST_SystemCocoa::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns3
|
||||
getMainDisplayDimensions(width, height);
|
||||
}
|
||||
|
||||
GHOST_IWindow *GHOST_SystemCocoa::createWindow(const STR_String &title,
|
||||
GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
|
@@ -106,7 +106,7 @@ class GHOST_SystemNULL : public GHOST_System {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_IWindow *createWindow(const STR_String &title,
|
||||
GHOST_IWindow *createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
|
@@ -49,7 +49,7 @@ GHOST_SystemSDL::~GHOST_SystemSDL()
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
GHOST_IWindow *GHOST_SystemSDL::createWindow(const STR_String &title,
|
||||
GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
|
@@ -80,7 +80,7 @@ class GHOST_SystemSDL : public GHOST_System {
|
||||
private:
|
||||
GHOST_TSuccess init();
|
||||
|
||||
GHOST_IWindow *createWindow(const STR_String &title,
|
||||
GHOST_IWindow *createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
|
1654
intern/ghost/intern/GHOST_SystemWayland.cpp
Normal file
1654
intern/ghost/intern/GHOST_SystemWayland.cpp
Normal file
File diff suppressed because it is too large
Load Diff
111
intern/ghost/intern/GHOST_SystemWayland.h
Normal file
111
intern/ghost/intern/GHOST_SystemWayland.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_SystemWayland class.
|
||||
*/
|
||||
|
||||
#ifndef __GHOST_SYSTEMWAYLAND_H__
|
||||
#define __GHOST_SYSTEMWAYLAND_H__
|
||||
|
||||
#include "../GHOST_Types.h"
|
||||
#include "GHOST_System.h"
|
||||
#include "GHOST_WindowWayland.h"
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include <xdg-shell-client-protocol.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
class GHOST_WindowWayland;
|
||||
|
||||
struct display_t;
|
||||
|
||||
class GHOST_SystemWayland : public GHOST_System {
|
||||
public:
|
||||
GHOST_SystemWayland();
|
||||
|
||||
~GHOST_SystemWayland() override;
|
||||
|
||||
bool processEvents(bool waitForEvent) override;
|
||||
|
||||
int toggleConsole(int action) override;
|
||||
|
||||
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const override;
|
||||
|
||||
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const override;
|
||||
|
||||
GHOST_TUns8 *getClipboard(bool selection) const override;
|
||||
|
||||
void putClipboard(GHOST_TInt8 *buffer, bool selection) const override;
|
||||
|
||||
GHOST_TUns8 getNumDisplays() const override;
|
||||
|
||||
GHOST_TSuccess getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const override;
|
||||
|
||||
GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) override;
|
||||
|
||||
void getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override;
|
||||
|
||||
void getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const override;
|
||||
|
||||
GHOST_IContext *createOffscreenContext() override;
|
||||
|
||||
GHOST_TSuccess disposeContext(GHOST_IContext *context) override;
|
||||
|
||||
GHOST_IWindow *createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_TDrawingContextType type,
|
||||
GHOST_GLSettings glSettings,
|
||||
const bool exclusive,
|
||||
const bool is_dialog,
|
||||
const GHOST_IWindow *parentWindow) override;
|
||||
|
||||
wl_display *display();
|
||||
|
||||
wl_compositor *compositor();
|
||||
|
||||
xdg_wm_base *shell();
|
||||
|
||||
void setSelection(const std::string &selection);
|
||||
|
||||
GHOST_TSuccess setCursorShape(GHOST_TStandardCursor shape);
|
||||
|
||||
GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape);
|
||||
|
||||
GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex,
|
||||
int sizey,
|
||||
int hotX,
|
||||
int hotY,
|
||||
bool canInvertColor);
|
||||
|
||||
GHOST_TSuccess setCursorVisibility(bool visible);
|
||||
|
||||
GHOST_TSuccess setCursorGrab(const GHOST_TGrabCursorMode mode, wl_surface *surface);
|
||||
|
||||
private:
|
||||
struct display_t *d;
|
||||
std::string selection;
|
||||
};
|
||||
|
||||
#endif /* __GHOST_SYSTEMWAYLAND_H__ */
|
@@ -282,7 +282,7 @@ void GHOST_SystemWin32::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns3
|
||||
height = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
}
|
||||
|
||||
GHOST_IWindow *GHOST_SystemWin32::createWindow(const STR_String &title,
|
||||
GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -938,100 +938,15 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
|
||||
window->updateMouseCapture(MouseReleased);
|
||||
}
|
||||
|
||||
/* Check for active Wintab mouse emulation in addition to a tablet in range because a proximity
|
||||
* leave event might have fired before the Windows mouse up event, thus there are still tablet
|
||||
* events to grab. The described behavior was observed in a Wacom Bamboo CTE-450.
|
||||
*/
|
||||
if (window->m_tabletInRange || window->wintabSysButPressed()) {
|
||||
if (window->useTabletAPI(GHOST_kTabletWintab) && processWintabEvents(type, window)) {
|
||||
// Wintab processing only handles in-contact events.
|
||||
return NULL;
|
||||
}
|
||||
else if (window->useTabletAPI(GHOST_kTabletNative)) {
|
||||
if (window->m_tabletInRange) {
|
||||
if (window->useTabletAPI(GHOST_kTabletNative)) {
|
||||
// Win32 Pointer processing handles input while in-range and in-contact events.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If using Wintab and this was a button down event but no button event was queued while
|
||||
// processing Wintab packets, fall through to create a button event.
|
||||
}
|
||||
|
||||
return new GHOST_EventButton(
|
||||
system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::processWintabEvents(GHOST_TEventType type,
|
||||
GHOST_WindowWin32 *window)
|
||||
{
|
||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||
|
||||
/* Only process Wintab packets if we can correlate them to a Window's mouse button event. When a
|
||||
* button event associated to a mouse button by Wintab occurs outside of WM_*BUTTON events,
|
||||
* there's no way to tell if other simultaneously pressed non-mouse mapped buttons are associated
|
||||
* to a modifier key (shift, alt, ctrl) or a system event (scroll, etc.) and thus it is not
|
||||
* possible to determine if a mouse click event should occur.
|
||||
*/
|
||||
if (!window->getMousePressed() && !window->wintabSysButPressed()) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
std::vector<GHOST_WintabInfoWin32> wintabInfo;
|
||||
if (!window->getWintabInfo(wintabInfo)) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
auto wtiIter = wintabInfo.begin();
|
||||
|
||||
/* We only process events that correlate to a mouse button events, so there may exist Wintab
|
||||
* button down events that were instead mapped to e.g. scroll still in the queue. We need to
|
||||
* skip those and find the last button down mapped to mouse buttons.
|
||||
*/
|
||||
if (!window->wintabSysButPressed()) {
|
||||
for (auto it = wtiIter; it != wintabInfo.end(); it++) {
|
||||
if (it->type == GHOST_kEventButtonDown) {
|
||||
wtiIter = it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; wtiIter != wintabInfo.end(); wtiIter++) {
|
||||
auto info = *wtiIter;
|
||||
|
||||
switch (info.type) {
|
||||
case GHOST_kEventButtonDown: {
|
||||
/* While changing windows with a tablet, Window's mouse button events normally occur before
|
||||
* tablet proximity events, so a button up event can't be differentiated as occurring from
|
||||
* a Wintab tablet or a normal mouse and a Ghost button event will always be generated.
|
||||
*
|
||||
* If we were called during a button down event create a ghost button down event, otherwise
|
||||
* don't duplicate the prior button down as it interrupts drawing immediately after
|
||||
* changing a window.
|
||||
*/
|
||||
if (type == GHOST_kEventButtonDown) {
|
||||
// Move cursor to point of contact because GHOST_EventButton does not include position.
|
||||
system->pushEvent(new GHOST_EventCursor(
|
||||
info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
|
||||
system->pushEvent(
|
||||
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
|
||||
}
|
||||
window->updateWintabSysBut(MousePressed);
|
||||
break;
|
||||
}
|
||||
case GHOST_kEventCursorMove:
|
||||
system->pushEvent(new GHOST_EventCursor(
|
||||
info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
|
||||
break;
|
||||
case GHOST_kEventButtonUp:
|
||||
system->pushEvent(
|
||||
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
|
||||
window->updateWintabSysBut(MouseReleased);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
system->getMilliSeconds(), type, window, mask, window->getTabletData());
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::processPointerEvents(
|
||||
@@ -1119,19 +1034,13 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
||||
GHOST_TInt32 x_screen, y_screen;
|
||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||
|
||||
if (window->m_tabletInRange || window->wintabSysButPressed()) {
|
||||
if (window->useTabletAPI(GHOST_kTabletWintab) &&
|
||||
processWintabEvents(GHOST_kEventCursorMove, window)) {
|
||||
return NULL;
|
||||
}
|
||||
else if (window->useTabletAPI(GHOST_kTabletNative)) {
|
||||
if (window->m_tabletInRange) {
|
||||
if (window->useTabletAPI(GHOST_kTabletNative)) {
|
||||
// Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet
|
||||
// input aren't normally generated when using WM_POINTER events, but manually moving the
|
||||
// system cursor as we do in WM_POINTER handling does.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If using Wintab but no button event is currently active, fall through to default handling
|
||||
}
|
||||
|
||||
system->getCursorPosition(x_screen, y_screen);
|
||||
@@ -1164,7 +1073,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
||||
window,
|
||||
x_screen + x_accum,
|
||||
y_screen + y_accum,
|
||||
GHOST_TABLET_DATA_NONE);
|
||||
window->getTabletData());
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1173,7 +1082,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
|
||||
window,
|
||||
x_screen,
|
||||
y_screen,
|
||||
GHOST_TABLET_DATA_NONE);
|
||||
window->getTabletData());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -1284,6 +1193,7 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type,
|
||||
|
||||
if (type == GHOST_kEventWindowActivate) {
|
||||
system->getWindowManager()->setActiveWindow(window);
|
||||
window->bringTabletContextToFront();
|
||||
}
|
||||
|
||||
return new GHOST_Event(system->getMilliSeconds(), type, window);
|
||||
@@ -1311,19 +1221,6 @@ GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
|
||||
system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data));
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::setTabletAPI(GHOST_TTabletAPI api)
|
||||
{
|
||||
GHOST_System::setTabletAPI(api);
|
||||
|
||||
GHOST_WindowManager *wm = getWindowManager();
|
||||
GHOST_WindowWin32 *activeWindow = (GHOST_WindowWin32 *)wm->getActiveWindow();
|
||||
|
||||
for (GHOST_IWindow *win : wm->getWindows()) {
|
||||
GHOST_WindowWin32 *windowsWindow = (GHOST_WindowWin32 *)win;
|
||||
windowsWindow->updateWintab(windowsWindow == activeWindow);
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax)
|
||||
{
|
||||
minmax->ptMinTrackSize.x = 320;
|
||||
@@ -1559,17 +1456,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
}
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Wintab events, processed
|
||||
// Tablet events, processed
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WT_INFOCHANGE: {
|
||||
window->processWintabInfoChangeEvent(lParam);
|
||||
case WT_PACKET:
|
||||
window->processWin32TabletEvent(wParam, lParam);
|
||||
break;
|
||||
}
|
||||
case WT_PROXIMITY: {
|
||||
bool inRange = LOWORD(lParam);
|
||||
window->processWintabProximityEvent(inRange);
|
||||
case WT_CSRCHANGE:
|
||||
case WT_PROXIMITY:
|
||||
window->processWin32TabletInitEvent();
|
||||
break;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Pointer events, processed
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -1708,9 +1603,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
* will not be dispatched to OUR active window if we minimize one of OUR windows. */
|
||||
if (LOWORD(wParam) == WA_INACTIVE)
|
||||
window->lostMouseCapture();
|
||||
|
||||
window->updateWintab(LOWORD(wParam) != WA_INACTIVE);
|
||||
|
||||
window->processWin32TabletActivateEvent(GET_WM_ACTIVATE_STATE(wParam, lParam));
|
||||
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
@@ -1768,11 +1661,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
else {
|
||||
event = processWindowEvent(GHOST_kEventWindowSize, window);
|
||||
}
|
||||
|
||||
if (msg == WM_SIZE && wParam == SIZE_MINIMIZED) {
|
||||
window->updateWintab(false);
|
||||
}
|
||||
|
||||
break;
|
||||
case WM_CAPTURECHANGED:
|
||||
window->lostMouseCapture();
|
||||
@@ -1823,12 +1711,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
}
|
||||
break;
|
||||
case WM_DISPLAYCHANGE:
|
||||
for (GHOST_IWindow *iter_win : system->getWindowManager()->getWindows()) {
|
||||
GHOST_WindowWin32 *iter_win32win = (GHOST_WindowWin32 *)iter_win;
|
||||
iter_win32win->processWintabDisplayChangeEvent();
|
||||
}
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Window events, ignored
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -126,7 +126,7 @@ class GHOST_SystemWin32 : public GHOST_System {
|
||||
* \param parentWindow Parent window
|
||||
* \return The new window (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IWindow *createWindow(const STR_String &title,
|
||||
GHOST_IWindow *createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -266,16 +266,6 @@ class GHOST_SystemWin32 : public GHOST_System {
|
||||
int mouseY,
|
||||
void *data);
|
||||
|
||||
/***************************************************************************************
|
||||
** Modify tablet API
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Set which tablet API to use.
|
||||
* \param api Enum indicating which API to use.
|
||||
*/
|
||||
void setTabletAPI(GHOST_TTabletAPI api) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initializes the system.
|
||||
|
@@ -338,7 +338,7 @@ void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32
|
||||
* \param parentWindow Parent window
|
||||
* \return The new window (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IWindow *GHOST_SystemX11::createWindow(const STR_String &title,
|
||||
GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -1881,7 +1881,7 @@ static GHOST_TKey ghost_key_from_keysym(const KeySym key)
|
||||
# endif
|
||||
#endif
|
||||
default:
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
printf("%s: unknown key: %lu / 0x%lx\n", __func__, key, key);
|
||||
#endif
|
||||
type = GHOST_kKeyUnknown;
|
||||
@@ -1905,7 +1905,7 @@ static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCo
|
||||
switch (id) {
|
||||
case MAKE_ID('T', 'L', 'D', 'E'):
|
||||
return GHOST_kKeyAccentGrave;
|
||||
#ifdef GHOST_DEBUG
|
||||
#ifdef WITH_GHOST_DEBUG
|
||||
default:
|
||||
printf("%s unhandled keycode: %.*s\n", __func__, XkbKeyNameLength, id_str);
|
||||
break;
|
||||
@@ -2456,7 +2456,7 @@ GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title,
|
||||
string cmd = "xdg-open \"" + string(link) + "\"";
|
||||
if (system(cmd.c_str()) != 0) {
|
||||
GHOST_PRINTF("GHOST_SystemX11::showMessageBox: Unable to run system command [%s]",
|
||||
cmd);
|
||||
cmd.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@@ -137,7 +137,7 @@ class GHOST_SystemX11 : public GHOST_System {
|
||||
* \param parentWindow Parent (embedder) window
|
||||
* \return The new window (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IWindow *createWindow(const STR_String &title,
|
||||
GHOST_IWindow *createWindow(const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
|
@@ -27,7 +27,6 @@
|
||||
|
||||
#include "GHOST_IWindow.h"
|
||||
|
||||
class STR_String;
|
||||
class GHOST_Context;
|
||||
|
||||
/**
|
||||
@@ -61,8 +60,8 @@ class GHOST_Window : public GHOST_IWindow {
|
||||
* \section Interface inherited from GHOST_IWindow left for derived class
|
||||
* implementation.
|
||||
* virtual bool getValid() const = 0;
|
||||
* virtual void setTitle(const STR_String& title) = 0;
|
||||
* virtual void getTitle(STR_String& title) const = 0;
|
||||
* virtual void setTitle(const char * title) = 0;
|
||||
* virtual std::string getTitle() const = 0;
|
||||
* virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
|
||||
* virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
|
||||
* virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
|
||||
|
@@ -30,7 +30,6 @@
|
||||
#endif // __APPLE__
|
||||
|
||||
#include "GHOST_Window.h"
|
||||
#include "STR_String.h"
|
||||
|
||||
@class CAMetalLayer;
|
||||
@class CocoaMetalView;
|
||||
@@ -58,7 +57,7 @@ class GHOST_WindowCocoa : public GHOST_Window {
|
||||
* \param stereoVisual Stereo visual for quad buffered stereo.
|
||||
*/
|
||||
GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
|
||||
const STR_String &title,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 bottom,
|
||||
GHOST_TUns32 width,
|
||||
@@ -92,13 +91,12 @@ class GHOST_WindowCocoa : public GHOST_Window {
|
||||
* Sets the title displayed in the title bar.
|
||||
* \param title The title to display in the title bar.
|
||||
*/
|
||||
void setTitle(const STR_String &title);
|
||||
|
||||
void setTitle(const char *title);
|
||||
/**
|
||||
* Returns the title displayed in the title bar.
|
||||
* \param title The title displayed in the title bar.
|
||||
*/
|
||||
void getTitle(STR_String &title) const;
|
||||
std::string getTitle() const;
|
||||
|
||||
/**
|
||||
* Returns the window rectangle dimensions.
|
||||
|
@@ -291,7 +291,7 @@
|
||||
/* clang-format on */
|
||||
|
||||
GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
|
||||
const STR_String &title,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 bottom,
|
||||
GHOST_TUns32 width,
|
||||
@@ -482,7 +482,7 @@ void *GHOST_WindowCocoa::getOSWindow() const
|
||||
return (void *)m_window;
|
||||
}
|
||||
|
||||
void GHOST_WindowCocoa::setTitle(const STR_String &title)
|
||||
void GHOST_WindowCocoa::setTitle(const char *title)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
@@ -524,7 +524,7 @@ void GHOST_WindowCocoa::setTitle(const STR_String &title)
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
void GHOST_WindowCocoa::getTitle(STR_String &title) const
|
||||
std::string GHOST_WindowCocoa::getTitle() const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid");
|
||||
|
||||
@@ -532,11 +532,14 @@ void GHOST_WindowCocoa::getTitle(STR_String &title) const
|
||||
|
||||
NSString *windowTitle = [m_window title];
|
||||
|
||||
std::string title;
|
||||
if (windowTitle != nil) {
|
||||
title = [windowTitle UTF8String];
|
||||
}
|
||||
|
||||
[pool drain];
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect &bounds) const
|
||||
|
@@ -26,7 +26,6 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
class STR_String;
|
||||
class GHOST_SystemNULL;
|
||||
|
||||
class GHOST_WindowNULL : public GHOST_Window {
|
||||
@@ -37,7 +36,7 @@ class GHOST_WindowNULL : public GHOST_Window {
|
||||
}
|
||||
|
||||
GHOST_WindowNULL(GHOST_SystemNULL *system,
|
||||
const STR_String &title,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -83,12 +82,12 @@ class GHOST_WindowNULL : public GHOST_Window {
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void setTitle(const STR_String &title)
|
||||
void setTitle(const char *title)
|
||||
{ /* nothing */
|
||||
}
|
||||
void getTitle(STR_String &title) const
|
||||
std::string getTitle() const
|
||||
{
|
||||
title = "untitled";
|
||||
return "untitled";
|
||||
}
|
||||
void getWindowBounds(GHOST_Rect &bounds) const
|
||||
{
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
|
||||
const STR_String &title,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -148,14 +148,14 @@ bool GHOST_WindowSDL::getValid() const
|
||||
return GHOST_Window::getValid() && m_valid_setup;
|
||||
}
|
||||
|
||||
void GHOST_WindowSDL::setTitle(const STR_String &title)
|
||||
void GHOST_WindowSDL::setTitle(const char *title)
|
||||
{
|
||||
SDL_SetWindowTitle(m_sdl_win, title.ReadPtr());
|
||||
SDL_SetWindowTitle(m_sdl_win, title);
|
||||
}
|
||||
|
||||
void GHOST_WindowSDL::getTitle(STR_String &title) const
|
||||
std::string GHOST_WindowSDL::getTitle() const
|
||||
{
|
||||
title = SDL_GetWindowTitle(m_sdl_win);
|
||||
return SDL_GetWindowTitle(m_sdl_win);
|
||||
}
|
||||
|
||||
void GHOST_WindowSDL::getWindowBounds(GHOST_Rect &bounds) const
|
||||
|
@@ -35,7 +35,6 @@ extern "C" {
|
||||
# error "SDL 2.0 or newer is needed to build with Ghost"
|
||||
#endif
|
||||
|
||||
class STR_String;
|
||||
class GHOST_SystemSDL;
|
||||
|
||||
class GHOST_WindowSDL : public GHOST_Window {
|
||||
@@ -49,7 +48,7 @@ class GHOST_WindowSDL : public GHOST_Window {
|
||||
|
||||
public:
|
||||
GHOST_WindowSDL(GHOST_SystemSDL *system,
|
||||
const STR_String &title,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -107,9 +106,9 @@ class GHOST_WindowSDL : public GHOST_Window {
|
||||
|
||||
GHOST_TSuccess setWindowCursorVisibility(bool visible);
|
||||
|
||||
void setTitle(const STR_String &title);
|
||||
void setTitle(const char *title);
|
||||
|
||||
void getTitle(STR_String &title) const;
|
||||
std::string getTitle() const;
|
||||
|
||||
GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
|
||||
|
||||
|
406
intern/ghost/intern/GHOST_WindowWayland.cpp
Normal file
406
intern/ghost/intern/GHOST_WindowWayland.cpp
Normal file
@@ -0,0 +1,406 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
#include "GHOST_WindowWayland.h"
|
||||
#include "GHOST_SystemWayland.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
#include "GHOST_ContextEGL.h"
|
||||
#include "GHOST_ContextNone.h"
|
||||
|
||||
#include <wayland-egl.h>
|
||||
|
||||
struct window_t {
|
||||
GHOST_WindowWayland *w;
|
||||
wl_surface *surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
wl_egl_window *egl_window;
|
||||
int32_t pending_width, pending_height;
|
||||
bool is_maximised;
|
||||
bool is_fullscreen;
|
||||
bool is_active;
|
||||
int32_t width, height;
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Wayland Interface Callbacks
|
||||
*
|
||||
* These callbacks are registered for Wayland interfaces and called when
|
||||
* an event is received from the compositor.
|
||||
* \{ */
|
||||
|
||||
static void toplevel_configure(
|
||||
void *data, xdg_toplevel * /*xdg_toplevel*/, int32_t width, int32_t height, wl_array *states)
|
||||
{
|
||||
window_t *win = static_cast<window_t *>(data);
|
||||
win->pending_width = width;
|
||||
win->pending_height = height;
|
||||
|
||||
win->is_maximised = false;
|
||||
win->is_fullscreen = false;
|
||||
win->is_active = false;
|
||||
|
||||
/* Note that the macro 'wl_array_for_each' would typically be used to simplify this logic,
|
||||
* however it's not compatible with C++, so perform casts instead.
|
||||
* If this needs to be done more often we could define our own C++ compatible macro. */
|
||||
for (enum xdg_toplevel_state *state = static_cast<xdg_toplevel_state *>(states->data);
|
||||
reinterpret_cast<uint8_t *>(state) < (static_cast<uint8_t *>(states->data) + states->size);
|
||||
state++) {
|
||||
switch (*state) {
|
||||
case XDG_TOPLEVEL_STATE_MAXIMIZED:
|
||||
win->is_maximised = true;
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
||||
win->is_fullscreen = true;
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_ACTIVATED:
|
||||
win->is_active = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void toplevel_close(void *data, xdg_toplevel * /*xdg_toplevel*/)
|
||||
{
|
||||
static_cast<window_t *>(data)->w->close();
|
||||
}
|
||||
|
||||
static const xdg_toplevel_listener toplevel_listener = {
|
||||
toplevel_configure,
|
||||
toplevel_close,
|
||||
};
|
||||
|
||||
static void surface_configure(void *data, xdg_surface *xdg_surface, uint32_t serial)
|
||||
{
|
||||
window_t *win = static_cast<window_t *>(data);
|
||||
|
||||
int w, h;
|
||||
wl_egl_window_get_attached_size(win->egl_window, &w, &h);
|
||||
if (win->pending_width != 0 && win->pending_height != 0 && win->pending_width != w &&
|
||||
win->pending_height != h) {
|
||||
win->width = win->pending_width;
|
||||
win->height = win->pending_height;
|
||||
wl_egl_window_resize(win->egl_window, win->pending_width, win->pending_height, 0, 0);
|
||||
win->pending_width = 0;
|
||||
win->pending_height = 0;
|
||||
win->w->notify_size();
|
||||
}
|
||||
|
||||
if (win->is_active) {
|
||||
win->w->activate();
|
||||
}
|
||||
else {
|
||||
win->w->deactivate();
|
||||
}
|
||||
|
||||
xdg_surface_ack_configure(xdg_surface, serial);
|
||||
}
|
||||
|
||||
static const xdg_surface_listener surface_listener = {
|
||||
surface_configure,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Ghost Implementation
|
||||
*
|
||||
* Wayland specific implementation of the GHOST_Window interface.
|
||||
* \{ */
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::hasCursorShape(GHOST_TStandardCursor cursorShape)
|
||||
{
|
||||
return m_system->hasCursorShape(cursorShape);
|
||||
}
|
||||
|
||||
GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
||||
const char *title,
|
||||
GHOST_TInt32 /*left*/,
|
||||
GHOST_TInt32 /*top*/,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
const GHOST_IWindow *parentWindow,
|
||||
GHOST_TDrawingContextType type,
|
||||
const bool stereoVisual,
|
||||
const bool exclusive)
|
||||
: GHOST_Window(width, height, state, stereoVisual, exclusive),
|
||||
m_system(system),
|
||||
w(new window_t)
|
||||
{
|
||||
w->w = this;
|
||||
|
||||
w->width = int32_t(width);
|
||||
w->height = int32_t(height);
|
||||
|
||||
/* Window surfaces. */
|
||||
w->surface = wl_compositor_create_surface(m_system->compositor());
|
||||
w->egl_window = wl_egl_window_create(w->surface, int(width), int(height));
|
||||
|
||||
w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->shell(), w->surface);
|
||||
w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
|
||||
|
||||
wl_surface_set_user_data(w->surface, this);
|
||||
|
||||
xdg_surface_add_listener(w->xdg_surface, &surface_listener, w);
|
||||
xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w);
|
||||
|
||||
if (parentWindow) {
|
||||
xdg_toplevel_set_parent(
|
||||
w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel);
|
||||
}
|
||||
|
||||
/* Call top-level callbacks. */
|
||||
wl_surface_commit(w->surface);
|
||||
wl_display_roundtrip(m_system->display());
|
||||
|
||||
setState(state);
|
||||
|
||||
setTitle(title);
|
||||
|
||||
/* EGL context. */
|
||||
if (setDrawingContextType(type) == GHOST_kFailure) {
|
||||
GHOST_PRINT("Failed to create EGL context" << std::endl);
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::close()
|
||||
{
|
||||
return m_system->pushEvent(
|
||||
new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowClose, this));
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::activate()
|
||||
{
|
||||
if (m_system->getWindowManager()->setActiveWindow(this) == GHOST_kFailure) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return m_system->pushEvent(
|
||||
new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowActivate, this));
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::deactivate()
|
||||
{
|
||||
m_system->getWindowManager()->setWindowInactive(this);
|
||||
return m_system->pushEvent(
|
||||
new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowDeactivate, this));
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::notify_size()
|
||||
{
|
||||
return m_system->pushEvent(
|
||||
new GHOST_Event(m_system->getMilliSeconds(), GHOST_kEventWindowSize, this));
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
|
||||
{
|
||||
return m_system->setCursorGrab(mode, w->surface);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor shape)
|
||||
{
|
||||
const GHOST_TSuccess ok = m_system->setCursorShape(shape);
|
||||
m_cursorShape = (ok == GHOST_kSuccess) ? shape : GHOST_kStandardCursorDefault;
|
||||
return ok;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex,
|
||||
int sizey,
|
||||
int hotX,
|
||||
int hotY,
|
||||
bool canInvertColor)
|
||||
{
|
||||
return m_system->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor);
|
||||
}
|
||||
|
||||
void GHOST_WindowWayland::setTitle(const char *title)
|
||||
{
|
||||
xdg_toplevel_set_title(w->xdg_toplevel, title);
|
||||
xdg_toplevel_set_app_id(w->xdg_toplevel, title);
|
||||
this->title = title;
|
||||
}
|
||||
|
||||
std::string GHOST_WindowWayland::getTitle() const
|
||||
{
|
||||
return this->title.empty() ? "untitled" : this->title;
|
||||
}
|
||||
|
||||
void GHOST_WindowWayland::getWindowBounds(GHOST_Rect &bounds) const
|
||||
{
|
||||
getClientBounds(bounds);
|
||||
}
|
||||
|
||||
void GHOST_WindowWayland::getClientBounds(GHOST_Rect &bounds) const
|
||||
{
|
||||
bounds.set(0, 0, w->width, w->height);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::setClientWidth(GHOST_TUns32 width)
|
||||
{
|
||||
return setClientSize(width, GHOST_TUns32(w->height));
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::setClientHeight(GHOST_TUns32 height)
|
||||
{
|
||||
return setClientSize(GHOST_TUns32(w->width), height);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
|
||||
{
|
||||
wl_egl_window_resize(w->egl_window, int(width), int(height), 0, 0);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
void GHOST_WindowWayland::screenToClient(GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32 &outX,
|
||||
GHOST_TInt32 &outY) const
|
||||
{
|
||||
outX = inX;
|
||||
outY = inY;
|
||||
}
|
||||
|
||||
void GHOST_WindowWayland::clientToScreen(GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32 &outX,
|
||||
GHOST_TInt32 &outY) const
|
||||
{
|
||||
outX = inX;
|
||||
outY = inY;
|
||||
}
|
||||
|
||||
GHOST_WindowWayland::~GHOST_WindowWayland()
|
||||
{
|
||||
releaseNativeHandles();
|
||||
|
||||
wl_egl_window_destroy(w->egl_window);
|
||||
xdg_toplevel_destroy(w->xdg_toplevel);
|
||||
xdg_surface_destroy(w->xdg_surface);
|
||||
wl_surface_destroy(w->surface);
|
||||
|
||||
delete w;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible)
|
||||
{
|
||||
return m_system->setCursorVisibility(visible);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state)
|
||||
{
|
||||
switch (state) {
|
||||
case GHOST_kWindowStateNormal:
|
||||
/* Unset states. */
|
||||
switch (getState()) {
|
||||
case GHOST_kWindowStateMaximized:
|
||||
xdg_toplevel_unset_maximized(w->xdg_toplevel);
|
||||
break;
|
||||
case GHOST_kWindowStateFullScreen:
|
||||
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GHOST_kWindowStateMaximized:
|
||||
xdg_toplevel_set_maximized(w->xdg_toplevel);
|
||||
break;
|
||||
case GHOST_kWindowStateMinimized:
|
||||
xdg_toplevel_set_minimized(w->xdg_toplevel);
|
||||
break;
|
||||
case GHOST_kWindowStateFullScreen:
|
||||
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
|
||||
break;
|
||||
case GHOST_kWindowStateEmbedded:
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TWindowState GHOST_WindowWayland::getState() const
|
||||
{
|
||||
if (w->is_fullscreen) {
|
||||
return GHOST_kWindowStateFullScreen;
|
||||
}
|
||||
else if (w->is_maximised) {
|
||||
return GHOST_kWindowStateMaximized;
|
||||
}
|
||||
else {
|
||||
return GHOST_kWindowStateNormal;
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::invalidate()
|
||||
{
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::setOrder(GHOST_TWindowOrder /*order*/)
|
||||
{
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const
|
||||
{
|
||||
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const
|
||||
{
|
||||
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param type The type of rendering context create.
|
||||
* \return Indication of success.
|
||||
*/
|
||||
GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType type)
|
||||
{
|
||||
GHOST_Context *context;
|
||||
switch (type) {
|
||||
case GHOST_kDrawingContextTypeNone:
|
||||
context = new GHOST_ContextNone(m_wantStereoVisual);
|
||||
break;
|
||||
case GHOST_kDrawingContextTypeOpenGL:
|
||||
context = new GHOST_ContextEGL(m_wantStereoVisual,
|
||||
EGLNativeWindowType(w->egl_window),
|
||||
EGLNativeDisplayType(m_system->display()),
|
||||
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||
3,
|
||||
3,
|
||||
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
|
||||
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
|
||||
EGL_OPENGL_API);
|
||||
break;
|
||||
}
|
||||
|
||||
return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr;
|
||||
}
|
||||
|
||||
/** \} */
|
121
intern/ghost/intern/GHOST_WindowWayland.h
Normal file
121
intern/ghost/intern/GHOST_WindowWayland.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup GHOST
|
||||
*
|
||||
* Declaration of GHOST_WindowWayland class.
|
||||
*/
|
||||
|
||||
#ifndef __GHOST_WINDOWWAYLAND_H__
|
||||
#define __GHOST_WINDOWWAYLAND_H__
|
||||
|
||||
#include "GHOST_Window.h"
|
||||
|
||||
class GHOST_SystemWayland;
|
||||
|
||||
struct window_t;
|
||||
|
||||
class GHOST_WindowWayland : public GHOST_Window {
|
||||
public:
|
||||
GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape) override;
|
||||
|
||||
GHOST_WindowWayland(GHOST_SystemWayland *system,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
const GHOST_IWindow *parentWindow,
|
||||
GHOST_TDrawingContextType type,
|
||||
const bool stereoVisual,
|
||||
const bool exclusive);
|
||||
|
||||
~GHOST_WindowWayland() override;
|
||||
|
||||
GHOST_TSuccess close();
|
||||
|
||||
GHOST_TSuccess activate();
|
||||
|
||||
GHOST_TSuccess deactivate();
|
||||
|
||||
GHOST_TSuccess notify_size();
|
||||
|
||||
protected:
|
||||
GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override;
|
||||
|
||||
GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override;
|
||||
|
||||
GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex,
|
||||
int sizey,
|
||||
int hotX,
|
||||
int hotY,
|
||||
bool canInvertColor) override;
|
||||
|
||||
void setTitle(const char *title) override;
|
||||
|
||||
std::string getTitle() const override;
|
||||
|
||||
void getWindowBounds(GHOST_Rect &bounds) const override;
|
||||
|
||||
void getClientBounds(GHOST_Rect &bounds) const override;
|
||||
|
||||
GHOST_TSuccess setClientWidth(GHOST_TUns32 width) override;
|
||||
|
||||
GHOST_TSuccess setClientHeight(GHOST_TUns32 height) override;
|
||||
|
||||
GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) override;
|
||||
|
||||
void screenToClient(GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32 &outX,
|
||||
GHOST_TInt32 &outY) const override;
|
||||
|
||||
void clientToScreen(GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32 &outX,
|
||||
GHOST_TInt32 &outY) const override;
|
||||
|
||||
GHOST_TSuccess setWindowCursorVisibility(bool visible) override;
|
||||
|
||||
GHOST_TSuccess setState(GHOST_TWindowState state) override;
|
||||
|
||||
GHOST_TWindowState getState() const override;
|
||||
|
||||
GHOST_TSuccess invalidate() override;
|
||||
|
||||
GHOST_TSuccess setOrder(GHOST_TWindowOrder order) override;
|
||||
|
||||
GHOST_TSuccess beginFullScreen() const override;
|
||||
|
||||
GHOST_TSuccess endFullScreen() const override;
|
||||
|
||||
private:
|
||||
GHOST_SystemWayland *m_system;
|
||||
struct window_t *w;
|
||||
std::string title;
|
||||
|
||||
/**
|
||||
* \param type The type of rendering context create.
|
||||
* \return Indication of success.
|
||||
*/
|
||||
GHOST_Context *newDrawingContext(GHOST_TDrawingContextType type) override;
|
||||
};
|
||||
|
||||
#endif // __GHOST_WINDOWWAYLAND_H__
|
@@ -59,7 +59,7 @@ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
}
|
||||
|
||||
GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
||||
const STR_String &title,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -81,7 +81,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
||||
m_nPressedButtons(0),
|
||||
m_customCursor(0),
|
||||
m_wantAlphaBackground(alphaBackground),
|
||||
m_wintab(),
|
||||
m_normal_state(GHOST_kWindowStateNormal),
|
||||
m_user32(NULL),
|
||||
m_fpGetPointerInfoHistory(NULL),
|
||||
@@ -90,6 +89,10 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
||||
m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : NULL),
|
||||
m_debug_context(is_debug)
|
||||
{
|
||||
// Initialize tablet variables
|
||||
memset(&m_wintab, 0, sizeof(m_wintab));
|
||||
m_tabletData = GHOST_TABLET_DATA_NONE;
|
||||
|
||||
// Create window
|
||||
if (state != GHOST_kWindowStateFullScreen) {
|
||||
RECT rect;
|
||||
@@ -155,7 +158,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
||||
height = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
|
||||
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
|
||||
m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name
|
||||
title_16, // pointer to window name
|
||||
wintype, // window style
|
||||
@@ -170,7 +173,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
||||
free(title_16);
|
||||
}
|
||||
else {
|
||||
wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
|
||||
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
|
||||
m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name
|
||||
title_16, // pointer to window name
|
||||
WS_MAXIMIZE, // window style
|
||||
@@ -294,25 +297,66 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
||||
m_user32, "GetPointerTouchInfoHistory");
|
||||
}
|
||||
|
||||
if ((m_wintab.handle = ::LoadLibrary("Wintab32.dll")) &&
|
||||
(m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA")) &&
|
||||
(m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA")) &&
|
||||
(m_wintab.get = (GHOST_WIN32_WTGet)::GetProcAddress(m_wintab.handle, "WTGetA")) &&
|
||||
(m_wintab.set = (GHOST_WIN32_WTSet)::GetProcAddress(m_wintab.handle, "WTSetA")) &&
|
||||
(m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose")) &&
|
||||
(m_wintab.packetsGet = (GHOST_WIN32_WTPacketsGet)::GetProcAddress(m_wintab.handle,
|
||||
"WTPacketsGet")) &&
|
||||
(m_wintab.queueSizeGet = (GHOST_WIN32_WTQueueSizeGet)::GetProcAddress(m_wintab.handle,
|
||||
"WTQueueSizeGet")) &&
|
||||
(m_wintab.queueSizeSet = (GHOST_WIN32_WTQueueSizeSet)::GetProcAddress(m_wintab.handle,
|
||||
"WTQueueSizeSet")) &&
|
||||
(m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable")) &&
|
||||
(m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap"))) {
|
||||
initializeWintab();
|
||||
// Determine which tablet API to use and enable it.
|
||||
updateWintab(true);
|
||||
}
|
||||
// Initialize Wintab
|
||||
m_wintab.handle = ::LoadLibrary("Wintab32.dll");
|
||||
if (m_wintab.handle) {
|
||||
// Get API functions
|
||||
m_wintab.info = (GHOST_WIN32_WTInfo)::GetProcAddress(m_wintab.handle, "WTInfoA");
|
||||
m_wintab.open = (GHOST_WIN32_WTOpen)::GetProcAddress(m_wintab.handle, "WTOpenA");
|
||||
m_wintab.close = (GHOST_WIN32_WTClose)::GetProcAddress(m_wintab.handle, "WTClose");
|
||||
m_wintab.packet = (GHOST_WIN32_WTPacket)::GetProcAddress(m_wintab.handle, "WTPacket");
|
||||
m_wintab.enable = (GHOST_WIN32_WTEnable)::GetProcAddress(m_wintab.handle, "WTEnable");
|
||||
m_wintab.overlap = (GHOST_WIN32_WTOverlap)::GetProcAddress(m_wintab.handle, "WTOverlap");
|
||||
|
||||
// Let's see if we can initialize tablet here.
|
||||
// Check if WinTab available by getting system context info.
|
||||
LOGCONTEXT lc = {0};
|
||||
lc.lcOptions |= CXO_SYSTEM;
|
||||
if (m_wintab.open && m_wintab.info && m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) {
|
||||
// Now init the tablet
|
||||
/* The maximum tablet size, pressure and orientation (tilt) */
|
||||
AXIS TabletX, TabletY, Pressure, Orientation[3];
|
||||
|
||||
// Open a Wintab context
|
||||
|
||||
// Open the context
|
||||
lc.lcPktData = PACKETDATA;
|
||||
lc.lcPktMode = PACKETMODE;
|
||||
lc.lcOptions |= CXO_MESSAGES;
|
||||
lc.lcMoveMask = PACKETDATA;
|
||||
|
||||
/* Set the entire tablet as active */
|
||||
m_wintab.info(WTI_DEVICES, DVC_X, &TabletX);
|
||||
m_wintab.info(WTI_DEVICES, DVC_Y, &TabletY);
|
||||
|
||||
/* get the max pressure, to divide into a float */
|
||||
BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
||||
if (pressureSupport)
|
||||
m_wintab.maxPressure = Pressure.axMax;
|
||||
else
|
||||
m_wintab.maxPressure = 0;
|
||||
|
||||
/* get the max tilt axes, to divide into floats */
|
||||
BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
|
||||
if (tiltSupport) {
|
||||
/* does the tablet support azimuth ([0]) and altitude ([1]) */
|
||||
if (Orientation[0].axResolution && Orientation[1].axResolution) {
|
||||
/* all this assumes the minimum is 0 */
|
||||
m_wintab.maxAzimuth = Orientation[0].axMax;
|
||||
m_wintab.maxAltitude = Orientation[1].axMax;
|
||||
}
|
||||
else { /* no so dont do tilt stuff */
|
||||
m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// The Wintab spec says we must open the context disabled if we are using cursor masks.
|
||||
m_wintab.tablet = m_wintab.open(m_hWnd, &lc, FALSE);
|
||||
if (m_wintab.enable && m_wintab.tablet) {
|
||||
m_wintab.enable(m_wintab.tablet, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
CoCreateInstance(
|
||||
CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
|
||||
}
|
||||
@@ -326,8 +370,8 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
|
||||
}
|
||||
|
||||
if (m_wintab.handle) {
|
||||
if (m_wintab.close && m_wintab.context) {
|
||||
m_wintab.close(m_wintab.context);
|
||||
if (m_wintab.close && m_wintab.tablet) {
|
||||
m_wintab.close(m_wintab.tablet);
|
||||
}
|
||||
|
||||
FreeLibrary(m_wintab.handle);
|
||||
@@ -386,19 +430,18 @@ HWND GHOST_WindowWin32::getHWND() const
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::setTitle(const STR_String &title)
|
||||
void GHOST_WindowWin32::setTitle(const char *title)
|
||||
{
|
||||
wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
|
||||
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
|
||||
::SetWindowTextW(m_hWnd, (wchar_t *)title_16);
|
||||
free(title_16);
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::getTitle(STR_String &title) const
|
||||
std::string GHOST_WindowWin32::getTitle() const
|
||||
{
|
||||
char buf[s_maxTitleLength]; /*CHANGE + never used yet*/
|
||||
::GetWindowText(m_hWnd, buf, s_maxTitleLength);
|
||||
STR_String temp(buf);
|
||||
title = buf;
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::getWindowBounds(GHOST_Rect &bounds) const
|
||||
@@ -776,27 +819,6 @@ bool GHOST_WindowWin32::getMousePressed() const
|
||||
return m_nPressedButtons;
|
||||
}
|
||||
|
||||
bool GHOST_WindowWin32::wintabSysButPressed() const
|
||||
{
|
||||
return m_wintab.numSysButtons;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::updateWintabSysBut(GHOST_MouseCaptureEventWin32 event)
|
||||
{
|
||||
switch (event) {
|
||||
case MousePressed:
|
||||
m_wintab.numSysButtons++;
|
||||
break;
|
||||
case MouseReleased:
|
||||
if (m_wintab.numSysButtons)
|
||||
m_wintab.numSysButtons--;
|
||||
break;
|
||||
case OperatorGrab:
|
||||
case OperatorUngrab:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const
|
||||
{
|
||||
// Convert GHOST cursor to Windows OEM cursor
|
||||
@@ -1000,103 +1022,6 @@ GHOST_TSuccess GHOST_WindowWin32::hasCursorShape(GHOST_TStandardCursor cursorSha
|
||||
return (getStandardCursor(cursorShape)) ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::updateWintab(bool active)
|
||||
{
|
||||
if (m_wintab.enable && m_wintab.overlap && m_wintab.context) {
|
||||
bool useWintab = useTabletAPI(GHOST_kTabletWintab);
|
||||
bool enable = active && useWintab;
|
||||
|
||||
// Disabling context while the Window is not minimized can cause issues on receiving Wintab
|
||||
// input while changing a window for some drivers, so only disable if either Wintab had been
|
||||
// disabled or the window is minimized.
|
||||
m_wintab.enable(m_wintab.context, useWintab && !::IsIconic(m_hWnd));
|
||||
m_wintab.overlap(m_wintab.context, enable);
|
||||
|
||||
if (!enable) {
|
||||
// WT_PROXIMITY event doesn't occur unless tablet's cursor leaves the proximity while the
|
||||
// window is active.
|
||||
m_tabletInRange = false;
|
||||
m_wintab.numSysButtons = 0;
|
||||
m_wintab.sysButtonsPressed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::initializeWintab()
|
||||
{
|
||||
// return if wintab library handle doesn't exist or wintab is already initialized
|
||||
if (!m_wintab.handle || m_wintab.context) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's see if we can initialize tablet here.
|
||||
// Check if WinTab available by getting system context info.
|
||||
LOGCONTEXT lc = {0};
|
||||
if (m_wintab.open && m_wintab.info && m_wintab.queueSizeGet && m_wintab.queueSizeSet &&
|
||||
m_wintab.info(WTI_DEFSYSCTX, 0, &lc)) {
|
||||
// Now init the tablet
|
||||
/* The pressure and orientation (tilt) */
|
||||
AXIS Pressure, Orientation[3];
|
||||
|
||||
// Open a Wintab context
|
||||
|
||||
// Open the context
|
||||
lc.lcPktData = PACKETDATA;
|
||||
lc.lcPktMode = PACKETMODE;
|
||||
lc.lcMoveMask = PACKETDATA;
|
||||
// Wacom maps y origin to the tablet's bottom
|
||||
// Invert to match Windows y origin mapping to the screen top
|
||||
lc.lcOutExtY = -lc.lcOutExtY;
|
||||
|
||||
m_wintab.info(WTI_INTERFACE, IFC_NDEVICES, &m_wintab.numDevices);
|
||||
|
||||
/* get the max pressure, to divide into a float */
|
||||
BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
||||
m_wintab.maxPressure = pressureSupport ? Pressure.axMax : 0;
|
||||
|
||||
/* get the max tilt axes, to divide into floats */
|
||||
BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
|
||||
/* does the tablet support azimuth ([0]) and altitude ([1]) */
|
||||
if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) {
|
||||
/* all this assumes the minimum is 0 */
|
||||
m_wintab.maxAzimuth = Orientation[0].axMax;
|
||||
m_wintab.maxAltitude = Orientation[1].axMax;
|
||||
}
|
||||
else { /* no so dont do tilt stuff */
|
||||
m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
|
||||
}
|
||||
|
||||
// The Wintab spec says we must open the context disabled if we are using cursor masks.
|
||||
m_wintab.context = m_wintab.open(m_hWnd, &lc, FALSE);
|
||||
|
||||
// Wintab provides no way to determine the maximum queue size aside from checking if attempts
|
||||
// to change the queue size are successful.
|
||||
const int maxQueue = 500;
|
||||
int queueSize = m_wintab.queueSizeGet(m_wintab.context);
|
||||
|
||||
while (queueSize < maxQueue) {
|
||||
int testSize = min(queueSize + 16, maxQueue);
|
||||
if (m_wintab.queueSizeSet(m_wintab.context, testSize)) {
|
||||
queueSize = testSize;
|
||||
}
|
||||
else {
|
||||
/* From Windows Wintab Documentation for WTQueueSizeSet:
|
||||
* "If the return value is zero, the context has no queue because the function deletes the
|
||||
* original queue before attempting to create a new one. The application must continue
|
||||
* calling the function with a smaller queue size until the function returns a non - zero
|
||||
* value."
|
||||
*
|
||||
* In our case we start with a known valid queue size and in the event of failure roll
|
||||
* back to the last valid queue size.
|
||||
*/
|
||||
m_wintab.queueSizeSet(m_wintab.context, queueSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_wintab.pkts.resize(queueSize);
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
|
||||
std::vector<GHOST_PointerInfoWin32> &outPointerInfo, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@@ -1179,20 +1104,28 @@ GHOST_TSuccess GHOST_WindowWin32::getPointerInfo(
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::processWintabDisplayChangeEvent()
|
||||
void GHOST_WindowWin32::setTabletData(GHOST_TabletData *pTabletData)
|
||||
{
|
||||
LOGCONTEXT lc_sys = {0}, lc_curr = {0};
|
||||
if (pTabletData) {
|
||||
m_tabletData = *pTabletData;
|
||||
}
|
||||
else {
|
||||
m_tabletData = GHOST_TABLET_DATA_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_wintab.info && m_wintab.get && m_wintab.set && m_wintab.info(WTI_DEFSYSCTX, 0, &lc_sys)) {
|
||||
void GHOST_WindowWin32::processWin32TabletActivateEvent(WORD state)
|
||||
{
|
||||
if (!useTabletAPI(GHOST_kTabletWintab)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_wintab.get(m_wintab.context, &lc_curr);
|
||||
if (m_wintab.enable && m_wintab.tablet) {
|
||||
m_wintab.enable(m_wintab.tablet, state);
|
||||
|
||||
lc_curr.lcOutOrgX = lc_sys.lcOutOrgX;
|
||||
lc_curr.lcOutOrgY = lc_sys.lcOutOrgY;
|
||||
lc_curr.lcOutExtX = lc_sys.lcOutExtX;
|
||||
lc_curr.lcOutExtY = -lc_sys.lcOutExtY;
|
||||
|
||||
m_wintab.set(m_wintab.context, &lc_curr);
|
||||
if (m_wintab.overlap && state) {
|
||||
m_wintab.overlap(m_wintab.tablet, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1202,7 +1135,7 @@ bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const
|
||||
return true;
|
||||
}
|
||||
else if (m_system->getTabletAPI() == GHOST_kTabletAutomatic) {
|
||||
if (m_wintab.numDevices)
|
||||
if (m_wintab.tablet)
|
||||
return api == GHOST_kTabletWintab;
|
||||
else
|
||||
return api == GHOST_kTabletNative;
|
||||
@@ -1212,180 +1145,115 @@ bool GHOST_WindowWin32::useTabletAPI(GHOST_TTabletAPI api) const
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::processWintabProximityEvent(bool inRange)
|
||||
void GHOST_WindowWin32::processWin32TabletInitEvent()
|
||||
{
|
||||
if (!useTabletAPI(GHOST_kTabletWintab)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's see if we can initialize tablet here
|
||||
if (m_wintab.info && m_wintab.context) {
|
||||
if (m_wintab.info && m_wintab.tablet) {
|
||||
AXIS Pressure, Orientation[3]; /* The maximum tablet size */
|
||||
|
||||
BOOL pressureSupport = m_wintab.info(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
||||
m_wintab.maxPressure = pressureSupport ? Pressure.axMax : 0;
|
||||
if (pressureSupport)
|
||||
m_wintab.maxPressure = Pressure.axMax;
|
||||
else
|
||||
m_wintab.maxPressure = 0;
|
||||
|
||||
BOOL tiltSupport = m_wintab.info(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
|
||||
/* does the tablet support azimuth ([0]) and altitude ([1]) */
|
||||
if (tiltSupport && Orientation[0].axResolution && Orientation[1].axResolution) {
|
||||
m_wintab.maxAzimuth = Orientation[0].axMax;
|
||||
m_wintab.maxAltitude = Orientation[1].axMax;
|
||||
}
|
||||
else { /* no so dont do tilt stuff */
|
||||
m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
|
||||
if (tiltSupport) {
|
||||
/* does the tablet support azimuth ([0]) and altitude ([1]) */
|
||||
if (Orientation[0].axResolution && Orientation[1].axResolution) {
|
||||
m_wintab.maxAzimuth = Orientation[0].axMax;
|
||||
m_wintab.maxAltitude = Orientation[1].axMax;
|
||||
}
|
||||
else { /* no so dont do tilt stuff */
|
||||
m_wintab.maxAzimuth = m_wintab.maxAltitude = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_tabletInRange = inRange;
|
||||
m_tabletData.Active = GHOST_kTabletModeNone;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::processWintabInfoChangeEvent(LPARAM lParam)
|
||||
{
|
||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
|
||||
|
||||
// Update number of connected Wintab digitizers
|
||||
if (LOWORD(lParam) == WTI_INTERFACE && HIWORD(lParam) == IFC_NDEVICES) {
|
||||
m_wintab.info(WTI_INTERFACE, IFC_NDEVICES, &m_wintab.numDevices);
|
||||
updateWintab((GHOST_WindowWin32 *)system->getWindowManager()->getActiveWindow() == this);
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::wintabMouseToGhost(UINT cursor,
|
||||
DWORD physicalButton,
|
||||
GHOST_TButtonMask &ghostButton)
|
||||
{
|
||||
const DWORD numButtons = 32;
|
||||
BYTE logicalButtons[numButtons] = {0};
|
||||
BYTE systemButtons[numButtons] = {0};
|
||||
|
||||
m_wintab.info(WTI_CURSORS + cursor, CSR_BUTTONMAP, &logicalButtons);
|
||||
m_wintab.info(WTI_CURSORS + cursor, CSR_SYSBTNMAP, &systemButtons);
|
||||
|
||||
if (physicalButton >= numButtons) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
BYTE lb = logicalButtons[physicalButton];
|
||||
|
||||
if (lb >= numButtons) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
switch (systemButtons[lb]) {
|
||||
case SBN_LCLICK:
|
||||
ghostButton = GHOST_kButtonMaskLeft;
|
||||
return GHOST_kSuccess;
|
||||
case SBN_RCLICK:
|
||||
ghostButton = GHOST_kButtonMaskRight;
|
||||
return GHOST_kSuccess;
|
||||
case SBN_MCLICK:
|
||||
ghostButton = GHOST_kButtonMaskMiddle;
|
||||
return GHOST_kSuccess;
|
||||
default:
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo)
|
||||
void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (!useTabletAPI(GHOST_kTabletWintab)) {
|
||||
return GHOST_kFailure;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(m_wintab.packetsGet && m_wintab.context)) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
if (m_wintab.packet && m_wintab.tablet) {
|
||||
PACKET pkt;
|
||||
if (m_wintab.packet((HCTX)lParam, wParam, &pkt)) {
|
||||
switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
|
||||
case 0:
|
||||
m_tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */
|
||||
break;
|
||||
case 1:
|
||||
m_tabletData.Active = GHOST_kTabletModeStylus; /* stylus */
|
||||
break;
|
||||
case 2:
|
||||
m_tabletData.Active = GHOST_kTabletModeEraser; /* eraser */
|
||||
break;
|
||||
}
|
||||
|
||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
|
||||
|
||||
const int numPackets = m_wintab.packetsGet(
|
||||
m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data());
|
||||
outWintabInfo.resize(numPackets);
|
||||
|
||||
for (int i = 0; i < numPackets; i++) {
|
||||
PACKET pkt = m_wintab.pkts[i];
|
||||
GHOST_TabletData tabletData = GHOST_TABLET_DATA_NONE;
|
||||
switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
|
||||
case 0:
|
||||
tabletData.Active = GHOST_kTabletModeNone; /* puck - not yet supported */
|
||||
break;
|
||||
case 1:
|
||||
tabletData.Active = GHOST_kTabletModeStylus; /* stylus */
|
||||
break;
|
||||
case 2:
|
||||
tabletData.Active = GHOST_kTabletModeEraser; /* eraser */
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_wintab.maxPressure > 0) {
|
||||
tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure;
|
||||
}
|
||||
|
||||
if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) {
|
||||
ORIENTATION ort = pkt.pkOrientation;
|
||||
float vecLen;
|
||||
float altRad, azmRad; /* in radians */
|
||||
|
||||
/*
|
||||
* from the wintab spec:
|
||||
* orAzimuth Specifies the clockwise rotation of the
|
||||
* cursor about the z axis through a full circular range.
|
||||
*
|
||||
* orAltitude Specifies the angle with the x-y plane
|
||||
* through a signed, semicircular range. Positive values
|
||||
* specify an angle upward toward the positive z axis;
|
||||
* negative values specify an angle downward toward the negative z axis.
|
||||
*
|
||||
* wintab.h defines .orAltitude as a UINT but documents .orAltitude
|
||||
* as positive for upward angles and negative for downward angles.
|
||||
* WACOM uses negative altitude values to show that the pen is inverted;
|
||||
* therefore we cast .orAltitude as an (int) and then use the absolute value.
|
||||
*/
|
||||
|
||||
/* convert raw fixed point data to radians */
|
||||
altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0);
|
||||
azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0);
|
||||
|
||||
/* find length of the stylus' projected vector on the XY plane */
|
||||
vecLen = cos(altRad);
|
||||
|
||||
/* from there calculate X and Y components based on azimuth */
|
||||
tabletData.Xtilt = sin(azmRad) * vecLen;
|
||||
tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
|
||||
}
|
||||
|
||||
outWintabInfo[i].x = pkt.pkX;
|
||||
outWintabInfo[i].y = pkt.pkY;
|
||||
|
||||
// Some Wintab libraries don't handle relative button input correctly, so we track button
|
||||
// presses manually.
|
||||
DWORD buttonsChanged = m_wintab.sysButtonsPressed ^ pkt.pkButtons;
|
||||
|
||||
// Find the index for the changed button from the button map.
|
||||
DWORD physicalButton = 0;
|
||||
for (DWORD diff = (unsigned)buttonsChanged >> 1; diff > 0; diff = (unsigned)diff >> 1) {
|
||||
physicalButton++;
|
||||
}
|
||||
|
||||
if (buttonsChanged &&
|
||||
wintabMouseToGhost(pkt.pkCursor, physicalButton, outWintabInfo[i].button)) {
|
||||
if (buttonsChanged & pkt.pkButtons) {
|
||||
outWintabInfo[i].type = GHOST_kEventButtonDown;
|
||||
if (m_wintab.maxPressure > 0) {
|
||||
m_tabletData.Pressure = (float)pkt.pkNormalPressure / (float)m_wintab.maxPressure;
|
||||
}
|
||||
else {
|
||||
outWintabInfo[i].type = GHOST_kEventButtonUp;
|
||||
m_tabletData.Pressure = 1.0f;
|
||||
}
|
||||
|
||||
if ((m_wintab.maxAzimuth > 0) && (m_wintab.maxAltitude > 0)) {
|
||||
ORIENTATION ort = pkt.pkOrientation;
|
||||
float vecLen;
|
||||
float altRad, azmRad; /* in radians */
|
||||
|
||||
/*
|
||||
* from the wintab spec:
|
||||
* orAzimuth Specifies the clockwise rotation of the
|
||||
* cursor about the z axis through a full circular range.
|
||||
*
|
||||
* orAltitude Specifies the angle with the x-y plane
|
||||
* through a signed, semicircular range. Positive values
|
||||
* specify an angle upward toward the positive z axis;
|
||||
* negative values specify an angle downward toward the negative z axis.
|
||||
*
|
||||
* wintab.h defines .orAltitude as a UINT but documents .orAltitude
|
||||
* as positive for upward angles and negative for downward angles.
|
||||
* WACOM uses negative altitude values to show that the pen is inverted;
|
||||
* therefore we cast .orAltitude as an (int) and then use the absolute value.
|
||||
*/
|
||||
|
||||
/* convert raw fixed point data to radians */
|
||||
altRad = (float)((fabs((float)ort.orAltitude) / (float)m_wintab.maxAltitude) * M_PI / 2.0);
|
||||
azmRad = (float)(((float)ort.orAzimuth / (float)m_wintab.maxAzimuth) * M_PI * 2.0);
|
||||
|
||||
/* find length of the stylus' projected vector on the XY plane */
|
||||
vecLen = cos(altRad);
|
||||
|
||||
/* from there calculate X and Y components based on azimuth */
|
||||
m_tabletData.Xtilt = sin(azmRad) * vecLen;
|
||||
m_tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
|
||||
}
|
||||
else {
|
||||
m_tabletData.Xtilt = 0.0f;
|
||||
m_tabletData.Ytilt = 0.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
outWintabInfo[i].type = GHOST_kEventCursorMove;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_wintab.sysButtonsPressed = pkt.pkButtons;
|
||||
|
||||
// Wintab does not support performance counters, so use low frequency counter instead
|
||||
outWintabInfo[i].time = system->tickCountToMillis(pkt.pkTime);
|
||||
outWintabInfo[i].tabletData = tabletData;
|
||||
void GHOST_WindowWin32::bringTabletContextToFront()
|
||||
{
|
||||
if (!useTabletAPI(GHOST_kTabletWintab)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
if (m_wintab.overlap && m_wintab.tablet) {
|
||||
m_wintab.overlap(m_wintab.tablet, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TUns16 GHOST_WindowWin32::getDPIHint()
|
||||
|
@@ -35,10 +35,11 @@
|
||||
# include "GHOST_ImeWin32.h"
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <wintab.h>
|
||||
#define PACKETDATA \
|
||||
(PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_X | PK_Y | PK_TIME)
|
||||
#define PACKETMODE 0
|
||||
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
|
||||
#define PACKETMODE PK_BUTTONS
|
||||
#include <pktdef.h>
|
||||
|
||||
class GHOST_SystemWin32;
|
||||
@@ -46,13 +47,9 @@ class GHOST_DropTargetWin32;
|
||||
|
||||
// typedefs for WinTab functions to allow dynamic loading
|
||||
typedef UINT(API *GHOST_WIN32_WTInfo)(UINT, UINT, LPVOID);
|
||||
typedef BOOL(API *GHOST_WIN32_WTGet)(HCTX, LPLOGCONTEXTA);
|
||||
typedef BOOL(API *GHOST_WIN32_WTSet)(HCTX, LPLOGCONTEXTA);
|
||||
typedef HCTX(API *GHOST_WIN32_WTOpen)(HWND, LPLOGCONTEXTA, BOOL);
|
||||
typedef BOOL(API *GHOST_WIN32_WTClose)(HCTX);
|
||||
typedef BOOL(API *GHOST_WIN32_WTPacketsGet)(HCTX, int, LPVOID);
|
||||
typedef int(API *GHOST_WIN32_WTQueueSizeGet)(HCTX);
|
||||
typedef BOOL(API *GHOST_WIN32_WTQueueSizeSet)(HCTX, int);
|
||||
typedef BOOL(API *GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID);
|
||||
typedef BOOL(API *GHOST_WIN32_WTEnable)(HCTX, BOOL);
|
||||
typedef BOOL(API *GHOST_WIN32_WTOverlap)(HCTX, BOOL);
|
||||
|
||||
@@ -233,14 +230,7 @@ struct GHOST_PointerInfoWin32 {
|
||||
GHOST_TButtonMask buttonMask;
|
||||
POINT pixelLocation;
|
||||
GHOST_TUns64 time;
|
||||
GHOST_TabletData tabletData;
|
||||
};
|
||||
|
||||
struct GHOST_WintabInfoWin32 {
|
||||
GHOST_TInt32 x, y;
|
||||
GHOST_TEventType type;
|
||||
GHOST_TButtonMask button;
|
||||
GHOST_TUns64 time;
|
||||
GHOST_TabletData tabletData;
|
||||
};
|
||||
|
||||
@@ -271,7 +261,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
||||
* \param parentWindowHwnd
|
||||
*/
|
||||
GHOST_WindowWin32(GHOST_SystemWin32 *system,
|
||||
const STR_String &title,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -306,13 +296,13 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
||||
* Sets the title displayed in the title bar.
|
||||
* \param title The title to display in the title bar.
|
||||
*/
|
||||
void setTitle(const STR_String &title);
|
||||
void setTitle(const char *title);
|
||||
|
||||
/**
|
||||
* Returns the title displayed in the title bar.
|
||||
* \param title The title displayed in the title bar.
|
||||
* \return The title displayed in the title bar.
|
||||
*/
|
||||
void getTitle(STR_String &title) const;
|
||||
std::string getTitle() const;
|
||||
|
||||
/**
|
||||
* Returns the window rectangle dimensions.
|
||||
@@ -434,16 +424,12 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
||||
HCURSOR getStandardCursor(GHOST_TStandardCursor shape) const;
|
||||
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const;
|
||||
|
||||
/**
|
||||
* Handle setup and switch between Wintab and Pointer APIs
|
||||
* \param active Whether the window is or will be in an active state
|
||||
*/
|
||||
void updateWintab(bool active);
|
||||
const GHOST_TabletData &getTabletData()
|
||||
{
|
||||
return m_tabletData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query whether given tablet API should be used.
|
||||
* \param api Tablet API to test.
|
||||
*/
|
||||
void setTabletData(GHOST_TabletData *tabletData);
|
||||
bool useTabletAPI(GHOST_TTabletAPI api) const;
|
||||
|
||||
/**
|
||||
@@ -456,28 +442,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
||||
WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
|
||||
/**
|
||||
* Handle Wintab coordinate changes when DisplayChange events occur.
|
||||
*/
|
||||
void processWintabDisplayChangeEvent();
|
||||
|
||||
/**
|
||||
* Set tablet details when a cursor enters range
|
||||
*/
|
||||
void processWintabProximityEvent(bool inRange);
|
||||
|
||||
/**
|
||||
* Handle Wintab info changes such as change in number of connected tablets.
|
||||
* \param lParam LPARAM of the event
|
||||
*/
|
||||
void processWintabInfoChangeEvent(LPARAM lParam);
|
||||
|
||||
/**
|
||||
* Translate Wintab packets into GHOST_WintabInfoWin32 structs.
|
||||
* \param outWintabInfo Storage to return resulting GHOST_WintabInfoWin32 structs
|
||||
* \return Success if able to read packets, even if there are none
|
||||
*/
|
||||
GHOST_TSuccess getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo);
|
||||
void processWin32TabletActivateEvent(WORD state);
|
||||
void processWin32TabletInitEvent();
|
||||
void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
|
||||
void bringTabletContextToFront();
|
||||
|
||||
GHOST_TSuccess beginFullScreen() const
|
||||
{
|
||||
@@ -497,19 +465,6 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
||||
*/
|
||||
bool getMousePressed() const;
|
||||
|
||||
/**
|
||||
* Get if there are currently pressed Wintab buttons associated to a Windows mouse button press
|
||||
* \return True if there are currently any pressed Wintab buttons associated to a Windows
|
||||
* mouse button press
|
||||
*/
|
||||
bool wintabSysButPressed() const;
|
||||
|
||||
/**
|
||||
* Register a Wintab button has been associated to a Windows mouse button press
|
||||
* \param event Whether the button was pressed or released
|
||||
*/
|
||||
void updateWintabSysBut(GHOST_MouseCaptureEventWin32 event);
|
||||
|
||||
/** Whether a tablet stylus is being tracked */
|
||||
bool m_tabletInRange;
|
||||
|
||||
@@ -593,49 +548,28 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
||||
static const wchar_t *s_windowClassName;
|
||||
static const int s_maxTitleLength;
|
||||
|
||||
/** Tablet data for GHOST */
|
||||
GHOST_TabletData m_tabletData;
|
||||
|
||||
/* Wintab API */
|
||||
struct {
|
||||
/** WinTab dll handle */
|
||||
HMODULE handle = NULL;
|
||||
HMODULE handle;
|
||||
|
||||
/** API functions */
|
||||
GHOST_WIN32_WTInfo info = NULL;
|
||||
GHOST_WIN32_WTGet get = NULL;
|
||||
GHOST_WIN32_WTSet set = NULL;
|
||||
GHOST_WIN32_WTOpen open = NULL;
|
||||
GHOST_WIN32_WTClose close = NULL;
|
||||
GHOST_WIN32_WTPacketsGet packetsGet = NULL;
|
||||
GHOST_WIN32_WTQueueSizeGet queueSizeGet = NULL;
|
||||
GHOST_WIN32_WTQueueSizeSet queueSizeSet = NULL;
|
||||
GHOST_WIN32_WTEnable enable = NULL;
|
||||
GHOST_WIN32_WTOverlap overlap = NULL;
|
||||
GHOST_WIN32_WTInfo info;
|
||||
GHOST_WIN32_WTOpen open;
|
||||
GHOST_WIN32_WTClose close;
|
||||
GHOST_WIN32_WTPacket packet;
|
||||
GHOST_WIN32_WTEnable enable;
|
||||
GHOST_WIN32_WTOverlap overlap;
|
||||
|
||||
/** Stores the Tablet context if detected Tablet features using WinTab.dll */
|
||||
HCTX context = NULL;
|
||||
/** Number of connected Wintab digitizers */
|
||||
UINT numDevices = 0;
|
||||
/** Number of cursors currently in contact mapped to system buttons */
|
||||
GHOST_TUns8 numSysButtons = 0;
|
||||
/** Cursors currently in contact mapped to system buttons */
|
||||
DWORD sysButtonsPressed = 0;
|
||||
LONG maxPressure = 0;
|
||||
LONG maxAzimuth = 0, maxAltitude = 0;
|
||||
/* Queue size doesn't change once set, so reuse the same buffer */
|
||||
std::vector<PACKET> pkts;
|
||||
HCTX tablet;
|
||||
LONG maxPressure;
|
||||
LONG maxAzimuth, maxAltitude;
|
||||
} m_wintab;
|
||||
|
||||
/**
|
||||
* Wintab setup
|
||||
*/
|
||||
void initializeWintab();
|
||||
|
||||
/**
|
||||
* Convert Wintab system mapped (mouse) buttons into Ghost button mask
|
||||
*/
|
||||
GHOST_TSuccess wintabMouseToGhost(UINT cursor,
|
||||
DWORD physicalButton,
|
||||
GHOST_TButtonMask &buttonMask);
|
||||
|
||||
GHOST_TWindowState m_normal_state;
|
||||
|
||||
/** user32 dll handle*/
|
||||
|
@@ -33,7 +33,6 @@
|
||||
#include "GHOST_IconX11.h"
|
||||
#include "GHOST_SystemX11.h"
|
||||
#include "GHOST_WindowX11.h"
|
||||
#include "STR_String.h"
|
||||
|
||||
#ifdef WITH_XDND
|
||||
# include "GHOST_DropTargetX11.h"
|
||||
@@ -61,6 +60,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
|
||||
@@ -212,7 +212,7 @@ static XVisualInfo *x11_visualinfo_from_glx(Display *display,
|
||||
|
||||
GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
|
||||
Display *display,
|
||||
const STR_String &title,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -414,9 +414,9 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system,
|
||||
/* XClassHint, title */
|
||||
{
|
||||
XClassHint *xclasshint = XAllocClassHint();
|
||||
const int len = title.Length() + 1;
|
||||
const int len = strlen(title) + 1;
|
||||
char *wmclass = (char *)malloc(sizeof(char) * len);
|
||||
memcpy(wmclass, title.ReadPtr(), len * sizeof(char));
|
||||
memcpy(wmclass, title, len * sizeof(char));
|
||||
xclasshint->res_name = wmclass;
|
||||
xclasshint->res_class = wmclass;
|
||||
XSetClassHint(m_display, m_window, xclasshint);
|
||||
@@ -617,7 +617,7 @@ bool GHOST_WindowX11::getValid() const
|
||||
return GHOST_Window::getValid() && m_valid_setup;
|
||||
}
|
||||
|
||||
void GHOST_WindowX11::setTitle(const STR_String &title)
|
||||
void GHOST_WindowX11::setTitle(const char *title)
|
||||
{
|
||||
Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0);
|
||||
Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0);
|
||||
@@ -627,8 +627,8 @@ void GHOST_WindowX11::setTitle(const STR_String &title)
|
||||
utf8str,
|
||||
8,
|
||||
PropModeReplace,
|
||||
(const unsigned char *)title.ReadPtr(),
|
||||
title.Length());
|
||||
(const unsigned char *)title,
|
||||
strlen(title));
|
||||
|
||||
/* This should convert to valid x11 string
|
||||
* and getTitle would need matching change */
|
||||
@@ -637,13 +637,14 @@ void GHOST_WindowX11::setTitle(const STR_String &title)
|
||||
XFlush(m_display);
|
||||
}
|
||||
|
||||
void GHOST_WindowX11::getTitle(STR_String &title) const
|
||||
std::string GHOST_WindowX11::getTitle() const
|
||||
{
|
||||
char *name = NULL;
|
||||
|
||||
XFetchName(m_display, m_window, &name);
|
||||
title = name ? name : "untitled";
|
||||
std::string title = name ? name : "untitled";
|
||||
XFree(name);
|
||||
return title;
|
||||
}
|
||||
|
||||
void GHOST_WindowX11::getWindowBounds(GHOST_Rect &bounds) const
|
||||
|
@@ -37,7 +37,6 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
class STR_String;
|
||||
class GHOST_SystemX11;
|
||||
|
||||
#ifdef WITH_XDND
|
||||
@@ -69,7 +68,7 @@ class GHOST_WindowX11 : public GHOST_Window {
|
||||
*/
|
||||
GHOST_WindowX11(GHOST_SystemX11 *system,
|
||||
Display *display,
|
||||
const STR_String &title,
|
||||
const char *title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
@@ -85,9 +84,9 @@ class GHOST_WindowX11 : public GHOST_Window {
|
||||
|
||||
bool getValid() const;
|
||||
|
||||
void setTitle(const STR_String &title);
|
||||
void setTitle(const char *title);
|
||||
|
||||
void getTitle(STR_String &title) const;
|
||||
std::string getTitle() const;
|
||||
|
||||
void getWindowBounds(GHOST_Rect &bounds) const;
|
||||
|
||||
|
@@ -22,7 +22,7 @@
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
|
||||
#if defined(WITH_X11)
|
||||
#if defined(WITH_GHOST_X11)
|
||||
# include "GHOST_ContextGLX.h"
|
||||
#elif defined(WIN32)
|
||||
# include "GHOST_ContextD3D.h"
|
||||
@@ -68,7 +68,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
|
||||
XrSystemId system_id,
|
||||
std::string *r_requirement_info) const override
|
||||
{
|
||||
#if defined(WITH_X11)
|
||||
#if defined(WITH_GHOST_X11)
|
||||
GHOST_ContextGLX *ctx_gl = static_cast<GHOST_ContextGLX *>(ghost_ctx);
|
||||
#else
|
||||
GHOST_ContextWGL *ctx_gl = static_cast<GHOST_ContextWGL *>(ghost_ctx);
|
||||
@@ -107,7 +107,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
|
||||
|
||||
void initFromGhostContext(GHOST_Context *ghost_ctx) override
|
||||
{
|
||||
#if defined(WITH_X11)
|
||||
#if defined(WITH_GHOST_X11)
|
||||
GHOST_ContextGLX *ctx_glx = static_cast<GHOST_ContextGLX *>(ghost_ctx);
|
||||
XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx->m_display, ctx_glx->m_fbconfig);
|
||||
|
||||
|
@@ -42,7 +42,7 @@
|
||||
#ifdef XR_USE_GRAPHICS_API_D3D12
|
||||
# include <d3d12.h>
|
||||
#endif
|
||||
#ifdef WITH_X11
|
||||
#ifdef WITH_GHOST_X11
|
||||
# include <GL/glxew.h>
|
||||
#endif
|
||||
|
||||
|
@@ -85,8 +85,9 @@ endif()
|
||||
# Libraries
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(WITH_X11 ON)
|
||||
set(WITH_GHOST_X11 ON)
|
||||
endif()
|
||||
|
||||
# for now... default to this
|
||||
add_definitions(-DWITH_GL_PROFILE_COMPAT)
|
||||
# BLF needs this to ignore GPU library
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
|
||||
#if defined(WIN32) || defined(__APPLE__)
|
||||
# ifdef WIN32
|
||||
@@ -43,7 +44,6 @@
|
||||
#endif // defined(WIN32) || defined(__APPLE__)
|
||||
|
||||
#include "GHOST_Rect.h"
|
||||
#include "STR_String.h"
|
||||
|
||||
#include "GHOST_IEvent.h"
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
@@ -427,8 +427,7 @@ Application::Application(GHOST_ISystem *system)
|
||||
fApp = this;
|
||||
|
||||
// Create the main window
|
||||
STR_String title1("gears - main window");
|
||||
m_mainWindow = system->createWindow(title1,
|
||||
m_mainWindow = system->createWindow("gears - main window",
|
||||
10,
|
||||
64,
|
||||
320,
|
||||
@@ -443,8 +442,7 @@ Application::Application(GHOST_ISystem *system)
|
||||
}
|
||||
|
||||
// Create a secondary window
|
||||
STR_String title2("gears - secondary window");
|
||||
m_secondaryWindow = system->createWindow(title2,
|
||||
m_secondaryWindow = system->createWindow("gears - secondary window",
|
||||
340,
|
||||
64,
|
||||
320,
|
||||
@@ -598,8 +596,7 @@ bool Application::processEvent(GHOST_IEvent *event)
|
||||
|
||||
case GHOST_kKeyW:
|
||||
if (m_mainWindow) {
|
||||
STR_String title;
|
||||
m_mainWindow->getTitle(title);
|
||||
std::string title = m_mainWindow->getTitle();
|
||||
title += "-";
|
||||
m_mainWindow->setTitle(title);
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@
|
||||
using libmv::CameraIntrinsics;
|
||||
using libmv::DivisionCameraIntrinsics;
|
||||
using libmv::PolynomialCameraIntrinsics;
|
||||
using libmv::NukeCameraIntrinsics;
|
||||
|
||||
libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
|
||||
const libmv_CameraIntrinsicsOptions* libmv_camera_intrinsics_options) {
|
||||
@@ -55,6 +56,14 @@ libmv_CameraIntrinsics *libmv_cameraIntrinsicsCopy(
|
||||
*division_intrinsics);
|
||||
break;
|
||||
}
|
||||
case libmv::DISTORTION_MODEL_NUKE:
|
||||
{
|
||||
const NukeCameraIntrinsics *nuke_intrinsics =
|
||||
static_cast<const NukeCameraIntrinsics*>(orig_intrinsics);
|
||||
new_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics,
|
||||
*nuke_intrinsics);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(!"Unknown distortion model");
|
||||
}
|
||||
@@ -136,6 +145,25 @@ void libmv_cameraIntrinsicsUpdate(
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBMV_DISTORTION_MODEL_NUKE:
|
||||
{
|
||||
assert(camera_intrinsics->GetDistortionModelType() ==
|
||||
libmv::DISTORTION_MODEL_NUKE);
|
||||
|
||||
NukeCameraIntrinsics *nuke_intrinsics =
|
||||
(NukeCameraIntrinsics *) camera_intrinsics;
|
||||
|
||||
double k1 = libmv_camera_intrinsics_options->nuke_k1;
|
||||
double k2 = libmv_camera_intrinsics_options->nuke_k2;
|
||||
|
||||
if (nuke_intrinsics->k1() != k1 ||
|
||||
nuke_intrinsics->k2() != k2) {
|
||||
nuke_intrinsics->SetDistortion(k1, k2);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(!"Unknown distortion model");
|
||||
}
|
||||
@@ -189,6 +217,17 @@ void libmv_cameraIntrinsicsExtractOptions(
|
||||
break;
|
||||
}
|
||||
|
||||
case libmv::DISTORTION_MODEL_NUKE:
|
||||
{
|
||||
const NukeCameraIntrinsics *nuke_intrinsics =
|
||||
static_cast<const NukeCameraIntrinsics *>(camera_intrinsics);
|
||||
camera_intrinsics_options->distortion_model =
|
||||
LIBMV_DISTORTION_MODEL_NUKE;
|
||||
camera_intrinsics_options->nuke_k1 = nuke_intrinsics->k1();
|
||||
camera_intrinsics_options->nuke_k2 = nuke_intrinsics->k2();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(!"Unknown distortion model");
|
||||
}
|
||||
@@ -316,6 +355,17 @@ static void libmv_cameraIntrinsicsFillFromOptions(
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBMV_DISTORTION_MODEL_NUKE:
|
||||
{
|
||||
NukeCameraIntrinsics *nuke_intrinsics =
|
||||
static_cast<NukeCameraIntrinsics*>(camera_intrinsics);
|
||||
|
||||
nuke_intrinsics->SetDistortion(
|
||||
camera_intrinsics_options->nuke_k1,
|
||||
camera_intrinsics_options->nuke_k2);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(!"Unknown distortion model");
|
||||
}
|
||||
@@ -331,6 +381,9 @@ CameraIntrinsics* libmv_cameraIntrinsicsCreateFromOptions(
|
||||
case LIBMV_DISTORTION_MODEL_DIVISION:
|
||||
camera_intrinsics = LIBMV_OBJECT_NEW(DivisionCameraIntrinsics);
|
||||
break;
|
||||
case LIBMV_DISTORTION_MODEL_NUKE:
|
||||
camera_intrinsics = LIBMV_OBJECT_NEW(NukeCameraIntrinsics);
|
||||
break;
|
||||
default:
|
||||
assert(!"Unknown distortion model");
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ typedef struct libmv_CameraIntrinsics libmv_CameraIntrinsics;
|
||||
enum {
|
||||
LIBMV_DISTORTION_MODEL_POLYNOMIAL = 0,
|
||||
LIBMV_DISTORTION_MODEL_DIVISION = 1,
|
||||
LIBMV_DISTORTION_MODEL_NUKE = 2,
|
||||
};
|
||||
|
||||
typedef struct libmv_CameraIntrinsicsOptions {
|
||||
@@ -45,6 +46,9 @@ typedef struct libmv_CameraIntrinsicsOptions {
|
||||
|
||||
// Division distortion model.
|
||||
double division_k1, division_k2;
|
||||
|
||||
// Nuke distortion model.
|
||||
double nuke_k1, nuke_k2;
|
||||
} libmv_CameraIntrinsicsOptions;
|
||||
|
||||
libmv_CameraIntrinsics *libmv_cameraIntrinsicsNew(
|
||||
|
@@ -66,18 +66,221 @@ enum {
|
||||
|
||||
namespace {
|
||||
|
||||
// Cost functor which computes reprojection error of 3D point X
|
||||
// on camera defined by angle-axis rotation and it's translation
|
||||
// (which are in the same block due to optimization reasons).
|
||||
bool NeedUseInvertIntrinsicsPipeline(const CameraIntrinsics *intrinsics) {
|
||||
const DistortionModelType distortion_model =
|
||||
intrinsics->GetDistortionModelType();
|
||||
return (distortion_model == DISTORTION_MODEL_NUKE);
|
||||
}
|
||||
|
||||
// Apply distortion model (distort the input) on the input point in the
|
||||
// normalized space to get distorted coordinate in the image space.
|
||||
//
|
||||
// This functor uses a radial distortion model.
|
||||
struct OpenCVReprojectionError {
|
||||
OpenCVReprojectionError(const DistortionModelType distortion_model,
|
||||
const double observed_x,
|
||||
const double observed_y,
|
||||
const double weight)
|
||||
: distortion_model_(distortion_model),
|
||||
observed_x_(observed_x), observed_y_(observed_y),
|
||||
// Using intrinsics values from the parameter block, which makes this function
|
||||
// suitable for use from a cost functor.
|
||||
//
|
||||
// Only use for distortion models which are analytically defined for their
|
||||
// Apply() function.
|
||||
//
|
||||
// The invariant_intrinsics are used to access intrinsics which are never
|
||||
// packed into parameter block: for example, distortion model type and image
|
||||
// dimension.
|
||||
template<typename T>
|
||||
void ApplyDistortionModelUsingIntrinsicsBlock(
|
||||
const CameraIntrinsics *invariant_intrinsics,
|
||||
const T* const intrinsics_block,
|
||||
const T& normalized_x, const T& normalized_y,
|
||||
T* distorted_x, T* distorted_y) {
|
||||
// Unpack the intrinsics.
|
||||
const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH];
|
||||
const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X];
|
||||
const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y];
|
||||
|
||||
// TODO(keir): Do early bailouts for zero distortion; these are expensive
|
||||
// jet operations.
|
||||
switch (invariant_intrinsics->GetDistortionModelType()) {
|
||||
case DISTORTION_MODEL_POLYNOMIAL:
|
||||
{
|
||||
const T& k1 = intrinsics_block[OFFSET_K1];
|
||||
const T& k2 = intrinsics_block[OFFSET_K2];
|
||||
const T& k3 = intrinsics_block[OFFSET_K3];
|
||||
const T& p1 = intrinsics_block[OFFSET_P1];
|
||||
const T& p2 = intrinsics_block[OFFSET_P2];
|
||||
|
||||
ApplyPolynomialDistortionModel(focal_length,
|
||||
focal_length,
|
||||
principal_point_x,
|
||||
principal_point_y,
|
||||
k1, k2, k3,
|
||||
p1, p2,
|
||||
normalized_x, normalized_y,
|
||||
distorted_x, distorted_y);
|
||||
return;
|
||||
}
|
||||
|
||||
case DISTORTION_MODEL_DIVISION:
|
||||
{
|
||||
const T& k1 = intrinsics_block[OFFSET_K1];
|
||||
const T& k2 = intrinsics_block[OFFSET_K2];
|
||||
|
||||
ApplyDivisionDistortionModel(focal_length,
|
||||
focal_length,
|
||||
principal_point_x,
|
||||
principal_point_y,
|
||||
k1, k2,
|
||||
normalized_x, normalized_y,
|
||||
distorted_x, distorted_y);
|
||||
return;
|
||||
}
|
||||
|
||||
case DISTORTION_MODEL_NUKE:
|
||||
{
|
||||
LOG(FATAL) << "Unsupported distortion model.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(FATAL) << "Unknown distortion model.";
|
||||
}
|
||||
|
||||
// Invert distortion model (undistort the input) on the input point in the
|
||||
// image space to get undistorted coordinate in the normalized space.
|
||||
//
|
||||
// Using intrinsics values from the parameter block, which makes this function
|
||||
// suitable for use from a cost functor.
|
||||
//
|
||||
// Only use for distortion models which are analytically defined for their
|
||||
// Invert() function.
|
||||
//
|
||||
// The invariant_intrinsics are used to access intrinsics which are never
|
||||
// packed into parameter block: for example, distortion model type and image
|
||||
// dimension.
|
||||
template<typename T>
|
||||
void InvertDistortionModelUsingIntrinsicsBlock(
|
||||
const CameraIntrinsics *invariant_intrinsics,
|
||||
const T* const intrinsics_block,
|
||||
const T& image_x, const T& image_y,
|
||||
T* normalized_x, T* normalized_y) {
|
||||
// Unpack the intrinsics.
|
||||
const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH];
|
||||
const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X];
|
||||
const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y];
|
||||
|
||||
// TODO(keir): Do early bailouts for zero distortion; these are expensive
|
||||
// jet operations.
|
||||
switch (invariant_intrinsics->GetDistortionModelType()) {
|
||||
case DISTORTION_MODEL_POLYNOMIAL:
|
||||
case DISTORTION_MODEL_DIVISION:
|
||||
LOG(FATAL) << "Unsupported distortion model.";
|
||||
return;
|
||||
|
||||
case DISTORTION_MODEL_NUKE:
|
||||
{
|
||||
const T& k1 = intrinsics_block[OFFSET_K1];
|
||||
const T& k2 = intrinsics_block[OFFSET_K2];
|
||||
|
||||
InvertNukeDistortionModel(focal_length,
|
||||
focal_length,
|
||||
principal_point_x,
|
||||
principal_point_y,
|
||||
invariant_intrinsics->image_width(),
|
||||
invariant_intrinsics->image_height(),
|
||||
k1, k2,
|
||||
image_x, image_y,
|
||||
normalized_x, normalized_y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(FATAL) << "Unknown distortion model.";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NormalizedToImageSpace(const T* const intrinsics_block,
|
||||
const T& normalized_x, const T& normalized_y,
|
||||
T* image_x, T* image_y) {
|
||||
// Unpack the intrinsics.
|
||||
const T& focal_length = intrinsics_block[OFFSET_FOCAL_LENGTH];
|
||||
const T& principal_point_x = intrinsics_block[OFFSET_PRINCIPAL_POINT_X];
|
||||
const T& principal_point_y = intrinsics_block[OFFSET_PRINCIPAL_POINT_Y];
|
||||
|
||||
*image_x = normalized_x * focal_length + principal_point_x;
|
||||
*image_y = normalized_y * focal_length + principal_point_y;
|
||||
}
|
||||
|
||||
// Cost functor which computes reprojection error of 3D point X on camera
|
||||
// defined by angle-axis rotation and it's translation (which are in the same
|
||||
// block due to optimization reasons).
|
||||
//
|
||||
// This functor can only be used for distortion models which have analytically
|
||||
// defined Apply() function.
|
||||
struct ReprojectionErrorApplyIntrinsics {
|
||||
ReprojectionErrorApplyIntrinsics(
|
||||
const CameraIntrinsics *invariant_intrinsics,
|
||||
const double observed_distorted_x,
|
||||
const double observed_distorted_y,
|
||||
const double weight)
|
||||
: invariant_intrinsics_(invariant_intrinsics),
|
||||
observed_distorted_x_(observed_distorted_x),
|
||||
observed_distorted_y_(observed_distorted_y),
|
||||
weight_(weight) {}
|
||||
|
||||
template <typename T>
|
||||
bool operator()(const T* const intrinsics,
|
||||
const T* const R_t, // Rotation denoted by angle axis
|
||||
// followed with translation
|
||||
const T* const X, // Point coordinates 3x1.
|
||||
T* residuals) const {
|
||||
// Compute projective coordinates: x = RX + t.
|
||||
T x[3];
|
||||
|
||||
ceres::AngleAxisRotatePoint(R_t, X, x);
|
||||
x[0] += R_t[3];
|
||||
x[1] += R_t[4];
|
||||
x[2] += R_t[5];
|
||||
|
||||
// Prevent points from going behind the camera.
|
||||
if (x[2] < T(0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute normalized coordinates: x /= x[2].
|
||||
T xn = x[0] / x[2];
|
||||
T yn = x[1] / x[2];
|
||||
|
||||
T predicted_distorted_x, predicted_distorted_y;
|
||||
ApplyDistortionModelUsingIntrinsicsBlock(
|
||||
invariant_intrinsics_,
|
||||
intrinsics,
|
||||
xn, yn,
|
||||
&predicted_distorted_x, &predicted_distorted_y);
|
||||
|
||||
// The error is the difference between the predicted and observed position.
|
||||
residuals[0] = (predicted_distorted_x - T(observed_distorted_x_)) * weight_;
|
||||
residuals[1] = (predicted_distorted_y - T(observed_distorted_y_)) * weight_;
|
||||
return true;
|
||||
}
|
||||
|
||||
const CameraIntrinsics *invariant_intrinsics_;
|
||||
const double observed_distorted_x_;
|
||||
const double observed_distorted_y_;
|
||||
const double weight_;
|
||||
};
|
||||
|
||||
// Cost functor which computes reprojection error of 3D point X on camera
|
||||
// defined by angle-axis rotation and it's translation (which are in the same
|
||||
// block due to optimization reasons).
|
||||
//
|
||||
// This functor can only be used for distortion models which have analytically
|
||||
// defined Invert() function.
|
||||
struct ReprojectionErrorInvertIntrinsics {
|
||||
ReprojectionErrorInvertIntrinsics(
|
||||
const CameraIntrinsics *invariant_intrinsics,
|
||||
const double observed_distorted_x,
|
||||
const double observed_distorted_y,
|
||||
const double weight)
|
||||
: invariant_intrinsics_(invariant_intrinsics),
|
||||
observed_distorted_x_(observed_distorted_x),
|
||||
observed_distorted_y_(observed_distorted_y),
|
||||
weight_(weight) {}
|
||||
|
||||
template <typename T>
|
||||
@@ -108,63 +311,37 @@ struct OpenCVReprojectionError {
|
||||
T xn = x[0] / x[2];
|
||||
T yn = x[1] / x[2];
|
||||
|
||||
T predicted_x, predicted_y;
|
||||
// Compute image space coordinate from normalized.
|
||||
T predicted_x = focal_length * xn + principal_point_x;
|
||||
T predicted_y = focal_length * yn + principal_point_y;
|
||||
|
||||
// Apply distortion to the normalized points to get (xd, yd).
|
||||
// TODO(keir): Do early bailouts for zero distortion; these are expensive
|
||||
// jet operations.
|
||||
switch (distortion_model_) {
|
||||
case DISTORTION_MODEL_POLYNOMIAL:
|
||||
{
|
||||
const T& k1 = intrinsics[OFFSET_K1];
|
||||
const T& k2 = intrinsics[OFFSET_K2];
|
||||
const T& k3 = intrinsics[OFFSET_K3];
|
||||
const T& p1 = intrinsics[OFFSET_P1];
|
||||
const T& p2 = intrinsics[OFFSET_P2];
|
||||
T observed_undistorted_normalized_x, observed_undistorted_normalized_y;
|
||||
InvertDistortionModelUsingIntrinsicsBlock(
|
||||
invariant_intrinsics_,
|
||||
intrinsics,
|
||||
T(observed_distorted_x_), T(observed_distorted_y_),
|
||||
&observed_undistorted_normalized_x, &observed_undistorted_normalized_y);
|
||||
|
||||
ApplyPolynomialDistortionModel(focal_length,
|
||||
focal_length,
|
||||
principal_point_x,
|
||||
principal_point_y,
|
||||
k1, k2, k3,
|
||||
p1, p2,
|
||||
xn, yn,
|
||||
&predicted_x,
|
||||
&predicted_y);
|
||||
break;
|
||||
}
|
||||
case DISTORTION_MODEL_DIVISION:
|
||||
{
|
||||
const T& k1 = intrinsics[OFFSET_K1];
|
||||
const T& k2 = intrinsics[OFFSET_K2];
|
||||
|
||||
ApplyDivisionDistortionModel(focal_length,
|
||||
focal_length,
|
||||
principal_point_x,
|
||||
principal_point_y,
|
||||
k1, k2,
|
||||
xn, yn,
|
||||
&predicted_x,
|
||||
&predicted_y);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(FATAL) << "Unknown distortion model";
|
||||
}
|
||||
T observed_undistorted_image_x, observed_undistorted_image_y;
|
||||
NormalizedToImageSpace(
|
||||
intrinsics,
|
||||
observed_undistorted_normalized_x, observed_undistorted_normalized_y,
|
||||
&observed_undistorted_image_x, &observed_undistorted_image_y);
|
||||
|
||||
// The error is the difference between the predicted and observed position.
|
||||
residuals[0] = (predicted_x - T(observed_x_)) * weight_;
|
||||
residuals[1] = (predicted_y - T(observed_y_)) * weight_;
|
||||
residuals[0] = (predicted_x - observed_undistorted_image_x) * weight_;
|
||||
residuals[1] = (predicted_y - observed_undistorted_image_y) * weight_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const DistortionModelType distortion_model_;
|
||||
const double observed_x_;
|
||||
const double observed_y_;
|
||||
const CameraIntrinsics *invariant_intrinsics_;
|
||||
const double observed_distorted_x_;
|
||||
const double observed_distorted_y_;
|
||||
const double weight_;
|
||||
};
|
||||
|
||||
// Print a message to the log which camera intrinsics are gonna to be optimixed.
|
||||
// Print a message to the log which camera intrinsics are gonna to be optimized.
|
||||
void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
|
||||
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
|
||||
LOG(INFO) << "Bundling only camera positions.";
|
||||
@@ -193,29 +370,29 @@ void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
|
||||
// Pack intrinsics from object to an array for easier
|
||||
// and faster minimization.
|
||||
void PackIntrinisicsIntoArray(const CameraIntrinsics &intrinsics,
|
||||
double ceres_intrinsics[OFFSET_MAX]) {
|
||||
ceres_intrinsics[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length();
|
||||
ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x();
|
||||
ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y();
|
||||
double intrinsics_block[OFFSET_MAX]) {
|
||||
intrinsics_block[OFFSET_FOCAL_LENGTH] = intrinsics.focal_length();
|
||||
intrinsics_block[OFFSET_PRINCIPAL_POINT_X] = intrinsics.principal_point_x();
|
||||
intrinsics_block[OFFSET_PRINCIPAL_POINT_Y] = intrinsics.principal_point_y();
|
||||
|
||||
int num_distortion_parameters = intrinsics.num_distortion_parameters();
|
||||
assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS);
|
||||
|
||||
const double *distortion_parameters = intrinsics.distortion_parameters();
|
||||
for (int i = 0; i < num_distortion_parameters; ++i) {
|
||||
ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i] =
|
||||
intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i] =
|
||||
distortion_parameters[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Unpack intrinsics back from an array to an object.
|
||||
void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX],
|
||||
void UnpackIntrinsicsFromArray(const double intrinsics_block[OFFSET_MAX],
|
||||
CameraIntrinsics *intrinsics) {
|
||||
intrinsics->SetFocalLength(ceres_intrinsics[OFFSET_FOCAL_LENGTH],
|
||||
ceres_intrinsics[OFFSET_FOCAL_LENGTH]);
|
||||
intrinsics->SetFocalLength(intrinsics_block[OFFSET_FOCAL_LENGTH],
|
||||
intrinsics_block[OFFSET_FOCAL_LENGTH]);
|
||||
|
||||
intrinsics->SetPrincipalPoint(ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X],
|
||||
ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]);
|
||||
intrinsics->SetPrincipalPoint(intrinsics_block[OFFSET_PRINCIPAL_POINT_X],
|
||||
intrinsics_block[OFFSET_PRINCIPAL_POINT_Y]);
|
||||
|
||||
int num_distortion_parameters = intrinsics->num_distortion_parameters();
|
||||
assert(num_distortion_parameters <= NUM_DISTORTION_COEFFICIENTS);
|
||||
@@ -223,7 +400,7 @@ void UnpackIntrinsicsFromArray(const double ceres_intrinsics[OFFSET_MAX],
|
||||
double *distortion_parameters = intrinsics->distortion_parameters();
|
||||
for (int i = 0; i < num_distortion_parameters; ++i) {
|
||||
distortion_parameters[i] =
|
||||
ceres_intrinsics[FIRST_DISTORTION_COEFFICIENT + i];
|
||||
intrinsics_block[FIRST_DISTORTION_COEFFICIENT + i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,68 +479,117 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
|
||||
vector<Vec6> *all_cameras_R_t,
|
||||
ceres::Problem *problem,
|
||||
BundleEvaluation *evaluation) {
|
||||
int max_track = tracks.MaxTrack();
|
||||
// Number of camera rotations equals to number of translation,
|
||||
int num_cameras = all_cameras_R_t->size();
|
||||
int num_points = 0;
|
||||
int max_track = tracks.MaxTrack();
|
||||
// Number of camera rotations equals to number of translation,
|
||||
int num_cameras = all_cameras_R_t->size();
|
||||
int num_points = 0;
|
||||
|
||||
vector<EuclideanPoint*> minimized_points;
|
||||
for (int i = 0; i <= max_track; i++) {
|
||||
EuclideanPoint *point = reconstruction->PointForTrack(i);
|
||||
if (point) {
|
||||
// We need to know whether the track is constant zero weight,
|
||||
// and it so it wouldn't have parameter block in the problem.
|
||||
//
|
||||
// Getting all markers for track is not so bac currently since
|
||||
// this code is only used by keyframe selection when there are
|
||||
// not so much tracks and only 2 frames anyway.
|
||||
vector<Marker> markera_of_track = tracks.MarkersForTrack(i);
|
||||
for (int j = 0; j < markera_of_track.size(); j++) {
|
||||
if (markera_of_track.at(j).weight != 0.0) {
|
||||
minimized_points.push_back(point);
|
||||
num_points++;
|
||||
break;
|
||||
}
|
||||
vector<EuclideanPoint*> minimized_points;
|
||||
for (int i = 0; i <= max_track; i++) {
|
||||
EuclideanPoint *point = reconstruction->PointForTrack(i);
|
||||
if (point) {
|
||||
// We need to know whether the track is a constant zero weight.
|
||||
// If it is so it wouldn't have a parameter block in the problem.
|
||||
//
|
||||
// Usually getting all markers of a track is considered slow, but this
|
||||
// code is only used by the keyframe selection code where there aren't
|
||||
// that many tracks in the storage and there are only 2 frames for each
|
||||
// of the tracks.
|
||||
vector<Marker> markera_of_track = tracks.MarkersForTrack(i);
|
||||
for (int j = 0; j < markera_of_track.size(); j++) {
|
||||
if (markera_of_track.at(j).weight != 0.0) {
|
||||
minimized_points.push_back(point);
|
||||
num_points++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LG << "Number of cameras " << num_cameras;
|
||||
LG << "Number of points " << num_points;
|
||||
LG << "Number of cameras " << num_cameras;
|
||||
LG << "Number of points " << num_points;
|
||||
|
||||
evaluation->num_cameras = num_cameras;
|
||||
evaluation->num_points = num_points;
|
||||
evaluation->num_cameras = num_cameras;
|
||||
evaluation->num_points = num_points;
|
||||
|
||||
if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix.
|
||||
ceres::CRSMatrix evaluated_jacobian;
|
||||
ceres::Problem::EvaluateOptions eval_options;
|
||||
if (evaluation->evaluate_jacobian) { // Evaluate jacobian matrix.
|
||||
ceres::CRSMatrix evaluated_jacobian;
|
||||
ceres::Problem::EvaluateOptions eval_options;
|
||||
|
||||
// Cameras goes first in the ordering.
|
||||
int max_image = tracks.MaxImage();
|
||||
for (int i = 0; i <= max_image; i++) {
|
||||
const EuclideanCamera *camera = reconstruction->CameraForImage(i);
|
||||
if (camera) {
|
||||
double *current_camera_R_t = &(*all_cameras_R_t)[i](0);
|
||||
// Cameras goes first in the ordering.
|
||||
int max_image = tracks.MaxImage();
|
||||
for (int i = 0; i <= max_image; i++) {
|
||||
const EuclideanCamera *camera = reconstruction->CameraForImage(i);
|
||||
if (camera) {
|
||||
double *current_camera_R_t = &(*all_cameras_R_t)[i](0);
|
||||
|
||||
// All cameras are variable now.
|
||||
problem->SetParameterBlockVariable(current_camera_R_t);
|
||||
// All cameras are variable now.
|
||||
problem->SetParameterBlockVariable(current_camera_R_t);
|
||||
|
||||
eval_options.parameter_blocks.push_back(current_camera_R_t);
|
||||
}
|
||||
eval_options.parameter_blocks.push_back(current_camera_R_t);
|
||||
}
|
||||
|
||||
// Points goes at the end of ordering,
|
||||
for (int i = 0; i < minimized_points.size(); i++) {
|
||||
EuclideanPoint *point = minimized_points.at(i);
|
||||
eval_options.parameter_blocks.push_back(&point->X(0));
|
||||
}
|
||||
|
||||
problem->Evaluate(eval_options,
|
||||
NULL, NULL, NULL,
|
||||
&evaluated_jacobian);
|
||||
|
||||
CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian);
|
||||
}
|
||||
|
||||
// Points goes at the end of ordering,
|
||||
for (int i = 0; i < minimized_points.size(); i++) {
|
||||
EuclideanPoint *point = minimized_points.at(i);
|
||||
eval_options.parameter_blocks.push_back(&point->X(0));
|
||||
}
|
||||
|
||||
problem->Evaluate(eval_options,
|
||||
NULL, NULL, NULL,
|
||||
&evaluated_jacobian);
|
||||
|
||||
CRSMatrixToEigenMatrix(evaluated_jacobian, &evaluation->jacobian);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CostFunction>
|
||||
void AddResidualBlockToProblemImpl(const CameraIntrinsics *invariant_intrinsics,
|
||||
double observed_x, double observed_y,
|
||||
double weight,
|
||||
double intrinsics_block[OFFSET_MAX],
|
||||
double *camera_R_t,
|
||||
EuclideanPoint *point,
|
||||
ceres::Problem* problem) {
|
||||
problem->AddResidualBlock(new ceres::AutoDiffCostFunction<
|
||||
CostFunction, 2, OFFSET_MAX, 6, 3>(
|
||||
new CostFunction(
|
||||
invariant_intrinsics,
|
||||
observed_x, observed_y,
|
||||
weight)),
|
||||
NULL,
|
||||
intrinsics_block,
|
||||
camera_R_t,
|
||||
&point->X(0));
|
||||
}
|
||||
|
||||
void AddResidualBlockToProblem(const CameraIntrinsics *invariant_intrinsics,
|
||||
const Marker &marker,
|
||||
double marker_weight,
|
||||
double intrinsics_block[OFFSET_MAX],
|
||||
double *camera_R_t,
|
||||
EuclideanPoint *point,
|
||||
ceres::Problem* problem) {
|
||||
if (NeedUseInvertIntrinsicsPipeline(invariant_intrinsics)) {
|
||||
AddResidualBlockToProblemImpl<ReprojectionErrorInvertIntrinsics>(
|
||||
invariant_intrinsics,
|
||||
marker.x, marker.y,
|
||||
marker_weight,
|
||||
intrinsics_block,
|
||||
camera_R_t,
|
||||
point,
|
||||
problem);
|
||||
} else {
|
||||
AddResidualBlockToProblemImpl<ReprojectionErrorApplyIntrinsics>(
|
||||
invariant_intrinsics,
|
||||
marker.x, marker.y,
|
||||
marker_weight,
|
||||
intrinsics_block,
|
||||
camera_R_t,
|
||||
point,
|
||||
problem);
|
||||
}
|
||||
}
|
||||
|
||||
// This is an utility function to only bundle 3D position of
|
||||
@@ -375,10 +601,10 @@ void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
|
||||
//
|
||||
// At this point we only need to bundle points positions, cameras
|
||||
// are to be totally still here.
|
||||
void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
|
||||
void EuclideanBundlePointsOnly(const CameraIntrinsics *invariant_intrinsics,
|
||||
const vector<Marker> &markers,
|
||||
vector<Vec6> &all_cameras_R_t,
|
||||
double ceres_intrinsics[OFFSET_MAX],
|
||||
double intrinsics_block[OFFSET_MAX],
|
||||
EuclideanReconstruction *reconstruction) {
|
||||
ceres::Problem::Options problem_options;
|
||||
ceres::Problem problem(problem_options);
|
||||
@@ -392,20 +618,16 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
|
||||
}
|
||||
|
||||
// Rotation of camera denoted in angle axis followed with
|
||||
// camera translaiton.
|
||||
// camera translation.
|
||||
double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
|
||||
|
||||
problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
|
||||
OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>(
|
||||
new OpenCVReprojectionError(
|
||||
distortion_model,
|
||||
marker.x,
|
||||
marker.y,
|
||||
1.0)),
|
||||
NULL,
|
||||
ceres_intrinsics,
|
||||
current_camera_R_t,
|
||||
&point->X(0));
|
||||
AddResidualBlockToProblem(invariant_intrinsics,
|
||||
marker,
|
||||
1.0,
|
||||
intrinsics_block,
|
||||
current_camera_R_t,
|
||||
point,
|
||||
&problem);
|
||||
|
||||
problem.SetParameterBlockConstant(current_camera_R_t);
|
||||
num_residuals++;
|
||||
@@ -417,7 +639,7 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
|
||||
return;
|
||||
}
|
||||
|
||||
problem.SetParameterBlockConstant(ceres_intrinsics);
|
||||
problem.SetParameterBlockConstant(intrinsics_block);
|
||||
|
||||
// Configure the solver.
|
||||
ceres::Solver::Options options;
|
||||
@@ -438,7 +660,6 @@ void EuclideanBundlePointsOnly(const DistortionModelType distortion_model,
|
||||
ceres::Solve(options, &problem, &summary);
|
||||
|
||||
LG << "Final report:\n" << summary.FullReport();
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -464,14 +685,14 @@ void EuclideanBundleCommonIntrinsics(
|
||||
LG << "Original intrinsics: " << *intrinsics;
|
||||
vector<Marker> markers = tracks.AllMarkers();
|
||||
|
||||
// N-th element denotes whether track N is a constant zero-weigthed track.
|
||||
// N-th element denotes whether track N is a constant zero-weighted track.
|
||||
vector<bool> zero_weight_tracks_flags(tracks.MaxTrack() + 1, true);
|
||||
|
||||
// Residual blocks with 10 parameters are unwieldly with Ceres, so pack the
|
||||
// intrinsics into a single block and rely on local parameterizations to
|
||||
// control which intrinsics are allowed to vary.
|
||||
double ceres_intrinsics[OFFSET_MAX];
|
||||
PackIntrinisicsIntoArray(*intrinsics, ceres_intrinsics);
|
||||
double intrinsics_block[OFFSET_MAX];
|
||||
PackIntrinisicsIntoArray(*intrinsics, intrinsics_block);
|
||||
|
||||
// Convert cameras rotations to angle axis and merge with translation
|
||||
// into single parameter block for maximal minimization speed.
|
||||
@@ -509,24 +730,20 @@ void EuclideanBundleCommonIntrinsics(
|
||||
}
|
||||
|
||||
// Rotation of camera denoted in angle axis followed with
|
||||
// camera translaiton.
|
||||
// camera translation.
|
||||
double *current_camera_R_t = &all_cameras_R_t[camera->image](0);
|
||||
|
||||
// Skip residual block for markers which does have absolutely
|
||||
// no affect on the final solution.
|
||||
// This way ceres is not gonna to go crazy.
|
||||
if (marker.weight != 0.0) {
|
||||
problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
|
||||
OpenCVReprojectionError, 2, OFFSET_MAX, 6, 3>(
|
||||
new OpenCVReprojectionError(
|
||||
intrinsics->GetDistortionModelType(),
|
||||
marker.x,
|
||||
marker.y,
|
||||
marker.weight)),
|
||||
NULL,
|
||||
ceres_intrinsics,
|
||||
current_camera_R_t,
|
||||
&point->X(0));
|
||||
AddResidualBlockToProblem(intrinsics,
|
||||
marker,
|
||||
marker.weight,
|
||||
intrinsics_block,
|
||||
current_camera_R_t,
|
||||
point,
|
||||
&problem);
|
||||
|
||||
// We lock the first camera to better deal with scene orientation ambiguity.
|
||||
if (!have_locked_camera) {
|
||||
@@ -561,7 +778,7 @@ void EuclideanBundleCommonIntrinsics(
|
||||
if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
|
||||
// No camera intrinsics are being refined,
|
||||
// set the whole parameter block as constant for best performance.
|
||||
problem.SetParameterBlockConstant(ceres_intrinsics);
|
||||
problem.SetParameterBlockConstant(intrinsics_block);
|
||||
} else {
|
||||
// Set the camera intrinsics that are not to be bundled as
|
||||
// constant using some macro trickery.
|
||||
@@ -586,7 +803,7 @@ void EuclideanBundleCommonIntrinsics(
|
||||
ceres::SubsetParameterization *subset_parameterization =
|
||||
new ceres::SubsetParameterization(OFFSET_MAX, constant_intrinsics);
|
||||
|
||||
problem.SetParameterization(ceres_intrinsics, subset_parameterization);
|
||||
problem.SetParameterization(intrinsics_block, subset_parameterization);
|
||||
}
|
||||
|
||||
// Configure the solver.
|
||||
@@ -616,7 +833,7 @@ void EuclideanBundleCommonIntrinsics(
|
||||
|
||||
// Copy intrinsics back.
|
||||
if (bundle_intrinsics != BUNDLE_NO_INTRINSICS)
|
||||
UnpackIntrinsicsFromArray(ceres_intrinsics, intrinsics);
|
||||
UnpackIntrinsicsFromArray(intrinsics_block, intrinsics);
|
||||
|
||||
LG << "Final intrinsics: " << *intrinsics;
|
||||
|
||||
@@ -641,10 +858,10 @@ void EuclideanBundleCommonIntrinsics(
|
||||
|
||||
if (zero_weight_markers.size()) {
|
||||
LG << "Refining position of constant zero-weighted tracks";
|
||||
EuclideanBundlePointsOnly(intrinsics->GetDistortionModelType(),
|
||||
EuclideanBundlePointsOnly(intrinsics,
|
||||
zero_weight_markers,
|
||||
all_cameras_R_t,
|
||||
ceres_intrinsics,
|
||||
intrinsics_block,
|
||||
reconstruction);
|
||||
}
|
||||
}
|
||||
|
@@ -131,6 +131,8 @@ void CameraIntrinsics::ResetLookupGrids() {
|
||||
undistort_.Reset();
|
||||
}
|
||||
|
||||
// Polynomial model.
|
||||
|
||||
PolynomialCameraIntrinsics::PolynomialCameraIntrinsics()
|
||||
: CameraIntrinsics() {
|
||||
SetRadialDistortion(0.0, 0.0, 0.0);
|
||||
@@ -193,6 +195,8 @@ void PolynomialCameraIntrinsics::InvertIntrinsics(
|
||||
normalized_y);
|
||||
}
|
||||
|
||||
// Division model.
|
||||
|
||||
DivisionCameraIntrinsics::DivisionCameraIntrinsics()
|
||||
: CameraIntrinsics() {
|
||||
SetDistortion(0.0, 0.0);
|
||||
@@ -241,6 +245,57 @@ void DivisionCameraIntrinsics::InvertIntrinsics(double image_x,
|
||||
normalized_y);
|
||||
}
|
||||
|
||||
// Nuke model.
|
||||
|
||||
NukeCameraIntrinsics::NukeCameraIntrinsics()
|
||||
: CameraIntrinsics() {
|
||||
SetDistortion(0.0, 0.0);
|
||||
}
|
||||
|
||||
NukeCameraIntrinsics::NukeCameraIntrinsics(
|
||||
const NukeCameraIntrinsics &from)
|
||||
: CameraIntrinsics(from) {
|
||||
SetDistortion(from.k1(), from.k1());
|
||||
}
|
||||
|
||||
void NukeCameraIntrinsics::SetDistortion(double k1, double k2) {
|
||||
parameters_[OFFSET_K1] = k1;
|
||||
parameters_[OFFSET_K2] = k2;
|
||||
ResetLookupGrids();
|
||||
}
|
||||
|
||||
void NukeCameraIntrinsics::ApplyIntrinsics(double normalized_x,
|
||||
double normalized_y,
|
||||
double *image_x,
|
||||
double *image_y) const {
|
||||
ApplyNukeDistortionModel(focal_length_x(),
|
||||
focal_length_y(),
|
||||
principal_point_x(),
|
||||
principal_point_y(),
|
||||
image_width(), image_height(),
|
||||
k1(), k2(),
|
||||
normalized_x,
|
||||
normalized_y,
|
||||
image_x,
|
||||
image_y);
|
||||
}
|
||||
|
||||
void NukeCameraIntrinsics::InvertIntrinsics(double image_x,
|
||||
double image_y,
|
||||
double *normalized_x,
|
||||
double *normalized_y) const {
|
||||
InvertNukeDistortionModel(focal_length_x(),
|
||||
focal_length_y(),
|
||||
principal_point_x(),
|
||||
principal_point_y(),
|
||||
image_width(), image_height(),
|
||||
k1(), k2(),
|
||||
image_x,
|
||||
image_y,
|
||||
normalized_x,
|
||||
normalized_y);
|
||||
}
|
||||
|
||||
std::ostream& operator <<(std::ostream &os,
|
||||
const CameraIntrinsics &intrinsics) {
|
||||
if (intrinsics.focal_length_x() == intrinsics.focal_length_x()) {
|
||||
@@ -281,6 +336,14 @@ std::ostream& operator <<(std::ostream &os,
|
||||
PRINT_NONZERO_COEFFICIENT(division_intrinsics, k2);
|
||||
break;
|
||||
}
|
||||
case DISTORTION_MODEL_NUKE:
|
||||
{
|
||||
const NukeCameraIntrinsics *nuke_intrinsics =
|
||||
static_cast<const NukeCameraIntrinsics *>(&intrinsics);
|
||||
PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k1);
|
||||
PRINT_NONZERO_COEFFICIENT(nuke_intrinsics, k2);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(FATAL) << "Unknown distortion model.";
|
||||
}
|
||||
|
@@ -276,7 +276,7 @@ class CameraIntrinsics {
|
||||
class PolynomialCameraIntrinsics : public CameraIntrinsics {
|
||||
public:
|
||||
// This constants defines an offset of corresponding coefficients
|
||||
// in the arameters_ array.
|
||||
// in the parameters_ array.
|
||||
enum {
|
||||
OFFSET_K1,
|
||||
OFFSET_K2,
|
||||
@@ -342,7 +342,7 @@ class PolynomialCameraIntrinsics : public CameraIntrinsics {
|
||||
class DivisionCameraIntrinsics : public CameraIntrinsics {
|
||||
public:
|
||||
// This constants defines an offset of corresponding coefficients
|
||||
// in the arameters_ array.
|
||||
// in the parameters_ array.
|
||||
enum {
|
||||
OFFSET_K1,
|
||||
OFFSET_K2,
|
||||
@@ -393,6 +393,60 @@ class DivisionCameraIntrinsics : public CameraIntrinsics {
|
||||
double parameters_[NUM_PARAMETERS];
|
||||
};
|
||||
|
||||
class NukeCameraIntrinsics : public CameraIntrinsics {
|
||||
public:
|
||||
// This constants defines an offset of corresponding coefficients
|
||||
// in the parameters_ array.
|
||||
enum {
|
||||
OFFSET_K1,
|
||||
OFFSET_K2,
|
||||
|
||||
// This defines the size of array which we need to have in order
|
||||
// to store all the coefficients.
|
||||
NUM_PARAMETERS,
|
||||
};
|
||||
|
||||
NukeCameraIntrinsics();
|
||||
NukeCameraIntrinsics(const NukeCameraIntrinsics &from);
|
||||
|
||||
DistortionModelType GetDistortionModelType() const {
|
||||
return DISTORTION_MODEL_NUKE;
|
||||
}
|
||||
|
||||
int num_distortion_parameters() const { return NUM_PARAMETERS; }
|
||||
double *distortion_parameters() { return parameters_; };
|
||||
const double *distortion_parameters() const { return parameters_; };
|
||||
|
||||
double k1() const { return parameters_[OFFSET_K1]; }
|
||||
double k2() const { return parameters_[OFFSET_K2]; }
|
||||
|
||||
// Set radial distortion coeffcients.
|
||||
void SetDistortion(double k1, double k2);
|
||||
|
||||
// Apply camera intrinsics to the normalized point to get image coordinates.
|
||||
//
|
||||
// This applies the lens distortion to a point which is in normalized
|
||||
// camera coordinates (i.e. the principal point is at (0, 0)) to get image
|
||||
// coordinates in pixels.
|
||||
void ApplyIntrinsics(double normalized_x,
|
||||
double normalized_y,
|
||||
double *image_x,
|
||||
double *image_y) const;
|
||||
|
||||
// Invert camera intrinsics on the image point to get normalized coordinates.
|
||||
//
|
||||
// This reverses the effect of lens distortion on a point which is in image
|
||||
// coordinates to get normalized camera coordinates.
|
||||
void InvertIntrinsics(double image_x,
|
||||
double image_y,
|
||||
double *normalized_x,
|
||||
double *normalized_y) const;
|
||||
|
||||
private:
|
||||
// Double-parameter division distortion model.
|
||||
double parameters_[NUM_PARAMETERS];
|
||||
};
|
||||
|
||||
/// A human-readable representation of the camera intrinsic parameters.
|
||||
std::ostream& operator <<(std::ostream &os,
|
||||
const CameraIntrinsics &intrinsics);
|
||||
|
@@ -194,4 +194,96 @@ void InvertDivisionDistortionModel(const double focal_length_x,
|
||||
*normalized_y = normalized(1);
|
||||
}
|
||||
|
||||
struct ApplyNukeIntrinsicsCostFunction {
|
||||
public:
|
||||
typedef Vec2 FMatrixType;
|
||||
typedef Vec2 XMatrixType;
|
||||
|
||||
ApplyNukeIntrinsicsCostFunction(const double focal_length_x,
|
||||
const double focal_length_y,
|
||||
const double principal_point_x,
|
||||
const double principal_point_y,
|
||||
const int image_width,
|
||||
const int image_height,
|
||||
const double k1,
|
||||
const double k2,
|
||||
const double expected_normalized_x,
|
||||
const double expected_normalized_y)
|
||||
: focal_length_x_(focal_length_x),
|
||||
focal_length_y_(focal_length_y),
|
||||
principal_point_x_(principal_point_x),
|
||||
principal_point_y_(principal_point_y),
|
||||
image_width_(image_width),
|
||||
image_height_(image_height),
|
||||
k1_(k1), k2_(k2),
|
||||
expected_normalized_x_(expected_normalized_x),
|
||||
expected_normalized_y_(expected_normalized_y) {}
|
||||
|
||||
Vec2 operator()(const Vec2 &image_coordinate) const {
|
||||
double actual_normalized_x, actual_normalized_y;
|
||||
|
||||
InvertNukeDistortionModel(focal_length_x_,
|
||||
focal_length_y_,
|
||||
principal_point_x_,
|
||||
principal_point_y_,
|
||||
image_width_, image_height_,
|
||||
k1_, k2_,
|
||||
image_coordinate(0), image_coordinate(1),
|
||||
&actual_normalized_x, &actual_normalized_y);
|
||||
|
||||
Vec2 fx;
|
||||
fx << (actual_normalized_x - expected_normalized_x_),
|
||||
(actual_normalized_y - expected_normalized_y_);
|
||||
return fx;
|
||||
}
|
||||
double focal_length_x_;
|
||||
double focal_length_y_;
|
||||
double principal_point_x_;
|
||||
double principal_point_y_;
|
||||
int image_width_;
|
||||
int image_height_;
|
||||
double k1_, k2_;
|
||||
double expected_normalized_x_, expected_normalized_y_;
|
||||
};
|
||||
|
||||
void ApplyNukeDistortionModel(const double focal_length_x,
|
||||
const double focal_length_y,
|
||||
const double principal_point_x,
|
||||
const double principal_point_y,
|
||||
const int image_width,
|
||||
const int image_height,
|
||||
const double k1,
|
||||
const double k2,
|
||||
const double normalized_x,
|
||||
const double normalized_y,
|
||||
double *image_x,
|
||||
double *image_y) {
|
||||
// Compute the initial guess. For a camera with no distortion, this will also
|
||||
// be the final answer; the LM iteration will terminate immediately.
|
||||
Vec2 image;
|
||||
image(0) = normalized_x * focal_length_x + principal_point_x;
|
||||
image(1) = normalized_y * focal_length_y + principal_point_y;
|
||||
|
||||
// TODO(sergey): Use Ceres minimizer instead.
|
||||
typedef LevenbergMarquardt<ApplyNukeIntrinsicsCostFunction> Solver;
|
||||
|
||||
ApplyNukeIntrinsicsCostFunction intrinsics_cost(focal_length_x,
|
||||
focal_length_y,
|
||||
principal_point_x,
|
||||
principal_point_y,
|
||||
image_width,
|
||||
image_height,
|
||||
k1, k2,
|
||||
normalized_x, normalized_y);
|
||||
Solver::SolverParameters params;
|
||||
Solver solver(intrinsics_cost);
|
||||
|
||||
/*Solver::Results results =*/ solver.minimize(params, &image);
|
||||
|
||||
// TODO(keir): Better error handling.
|
||||
|
||||
*image_x = image(0);
|
||||
*image_y = image(1);
|
||||
}
|
||||
|
||||
} // namespace libmv
|
||||
|
@@ -21,11 +21,14 @@
|
||||
#ifndef LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_
|
||||
#define LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace libmv {
|
||||
|
||||
enum DistortionModelType {
|
||||
DISTORTION_MODEL_POLYNOMIAL,
|
||||
DISTORTION_MODEL_DIVISION
|
||||
DISTORTION_MODEL_DIVISION,
|
||||
DISTORTION_MODEL_NUKE,
|
||||
};
|
||||
|
||||
// Invert camera intrinsics on the image point to get normalized coordinates.
|
||||
@@ -126,6 +129,79 @@ inline void ApplyDivisionDistortionModel(const T &focal_length_x,
|
||||
*image_y = focal_length_y * yd + principal_point_y;
|
||||
}
|
||||
|
||||
// Invert camera intrinsics on the image point to get normalized coordinates.
|
||||
// This inverts the radial lens distortion to a point which is in image pixel
|
||||
// coordinates to get normalized coordinates.
|
||||
//
|
||||
// Uses Nuke distortion model.
|
||||
template <typename T>
|
||||
void InvertNukeDistortionModel(const T &focal_length_x,
|
||||
const T &focal_length_y,
|
||||
const T &principal_point_x,
|
||||
const T &principal_point_y,
|
||||
const int image_width,
|
||||
const int image_height,
|
||||
const T &k1,
|
||||
const T &k2,
|
||||
const T &image_x,
|
||||
const T &image_y,
|
||||
T *normalized_x,
|
||||
T *normalized_y) {
|
||||
// According to the documentation:
|
||||
//
|
||||
// xu = xd / (1 + k0 * rd^2 + k1 * rd^4)
|
||||
// yu = yd / (1 + k0 * rd^2 + k1 * rd^4)
|
||||
//
|
||||
// Legend:
|
||||
// (xd, yd) are the distorted cartesian coordinates,
|
||||
// (rd, phid) are the distorted polar coordinates,
|
||||
// (xu, yu) are the undistorted cartesian coordinates,
|
||||
// (ru, phiu) are the undistorted polar coordinates,
|
||||
// the k-values are the distortion coefficients.
|
||||
//
|
||||
// The coordinate systems are relative to the distortion centre.
|
||||
|
||||
const int max_image_size = std::max(image_width, image_height);
|
||||
const double max_half_image_size = max_image_size * 0.5;
|
||||
|
||||
if (max_half_image_size == 0.0) {
|
||||
*normalized_x = image_x * max_half_image_size / focal_length_x;
|
||||
*normalized_y = image_y * max_half_image_size / focal_length_y;
|
||||
return;
|
||||
}
|
||||
|
||||
const T xd = (image_x - principal_point_x) / max_half_image_size;
|
||||
const T yd = (image_y - principal_point_y) / max_half_image_size;
|
||||
|
||||
T rd2 = xd*xd + yd*yd;
|
||||
T rd4 = rd2 * rd2;
|
||||
T r_coeff = T(1) / (T(1) + k1*rd2 + k2*rd4);
|
||||
T xu = xd * r_coeff;
|
||||
T yu = yd * r_coeff;
|
||||
|
||||
*normalized_x = xu * max_half_image_size / focal_length_x;
|
||||
*normalized_y = yu * max_half_image_size / focal_length_y;
|
||||
}
|
||||
|
||||
// Apply camera intrinsics to the normalized point to get image coordinates.
|
||||
// This applies the radial lens distortion to a point which is in normalized
|
||||
// camera coordinates (i.e. the principal point is at (0, 0)) to get image
|
||||
// coordinates in pixels. Templated for use with autodifferentiation.
|
||||
//
|
||||
// Uses Nuke distortion model.
|
||||
void ApplyNukeDistortionModel(const double focal_length_x,
|
||||
const double focal_length_y,
|
||||
const double principal_point_x,
|
||||
const double principal_point_y,
|
||||
const int image_width,
|
||||
const int image_height,
|
||||
const double k1,
|
||||
const double k2,
|
||||
const double normalized_x,
|
||||
const double normalized_y,
|
||||
double *image_x,
|
||||
double *image_y);
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_SIMPLE_PIPELINE_DISTORTION_MODELS_H_
|
||||
|
1
intern/mantaflow/extern/manta_fluid_API.h
vendored
1
intern/mantaflow/extern/manta_fluid_API.h
vendored
@@ -107,6 +107,7 @@ float *manta_get_phistatic_in(struct MANTA *fluid);
|
||||
float *manta_get_phiobs_in(struct MANTA *fluid);
|
||||
float *manta_get_phiobsstatic_in(struct MANTA *fluid);
|
||||
float *manta_get_phiout_in(struct MANTA *fluid);
|
||||
float *manta_get_phioutstatic_in(struct MANTA *fluid);
|
||||
|
||||
/* Smoke functions */
|
||||
void manta_smoke_export_script(struct MANTA *smoke, struct FluidModifierData *mmd);
|
||||
|
@@ -61,28 +61,29 @@ int MANTA::with_debug(0);
|
||||
MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
|
||||
{
|
||||
if (with_debug)
|
||||
std::cout << "MANTA: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", "
|
||||
std::cout << "FLUID: " << mCurrentID << " with res(" << res[0] << ", " << res[1] << ", "
|
||||
<< res[2] << ")" << std::endl;
|
||||
|
||||
mmd->domain->fluid = this;
|
||||
|
||||
mUsingLiquid = (mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID);
|
||||
mUsingSmoke = (mmd->domain->type == FLUID_DOMAIN_TYPE_GAS);
|
||||
mUsingHeat = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke;
|
||||
mUsingFire = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke;
|
||||
mUsingColors = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke;
|
||||
mUsingNoise = (mmd->domain->flags & FLUID_DOMAIN_USE_NOISE) && mUsingSmoke;
|
||||
mUsingFractions = (mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS) && mUsingLiquid;
|
||||
mUsingMesh = (mmd->domain->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid;
|
||||
mUsingMVel = (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid;
|
||||
mUsingGuiding = (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE);
|
||||
mUsingDrops = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) && mUsingLiquid;
|
||||
mUsingBubbles = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE) && mUsingLiquid;
|
||||
mUsingFloats = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_FOAM) && mUsingLiquid;
|
||||
mUsingTracers = (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_TRACER) && mUsingLiquid;
|
||||
mUsingMesh = (mmd->domain->flags & FLUID_DOMAIN_USE_MESH) && mUsingLiquid;
|
||||
mUsingMVel = (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS) && mUsingLiquid;
|
||||
|
||||
mUsingHeat = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) && mUsingSmoke;
|
||||
mUsingFire = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) && mUsingSmoke;
|
||||
mUsingColors = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) && mUsingSmoke;
|
||||
mUsingObstacle = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE);
|
||||
mUsingInvel = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL);
|
||||
mUsingOutflow = (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW);
|
||||
mUsingGuiding = (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE);
|
||||
|
||||
// Simulation constants
|
||||
mTempAmb = 0; // TODO: Maybe use this later for buoyancy calculation
|
||||
@@ -140,6 +141,7 @@ MANTA::MANTA(int *res, FluidModifierData *mmd) : mCurrentID(++solverID)
|
||||
mPhiIn = nullptr;
|
||||
mPhiStaticIn = nullptr;
|
||||
mPhiOutIn = nullptr;
|
||||
mPhiOutStaticIn = nullptr;
|
||||
mPhi = nullptr;
|
||||
|
||||
// Mesh
|
||||
@@ -566,7 +568,7 @@ bool MANTA::runPythonString(std::vector<std::string> commands)
|
||||
void MANTA::initializeMantaflow()
|
||||
{
|
||||
if (with_debug)
|
||||
std::cout << "Fluid: Initializing Mantaflow framework." << std::endl;
|
||||
std::cout << "Fluid: Initializing Mantaflow framework" << std::endl;
|
||||
|
||||
std::string filename = "manta_scene_" + std::to_string(mCurrentID) + ".py";
|
||||
std::vector<std::string> fill = std::vector<std::string>();
|
||||
@@ -581,7 +583,7 @@ void MANTA::initializeMantaflow()
|
||||
void MANTA::terminateMantaflow()
|
||||
{
|
||||
if (with_debug)
|
||||
std::cout << "Fluid: Releasing Mantaflow framework." << std::endl;
|
||||
std::cout << "Fluid: Releasing Mantaflow framework" << std::endl;
|
||||
|
||||
PyGILState_STATE gilstate = PyGILState_Ensure();
|
||||
Pb::finalize(); // Namespace from Mantaflow (registry)
|
||||
@@ -633,36 +635,36 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
|
||||
if (varName == "USING_SMOKE")
|
||||
ss << ((mmd->domain->type == FLUID_DOMAIN_TYPE_GAS) ? "True" : "False");
|
||||
else if (varName == "USING_LIQUID")
|
||||
if (varName == "USING_LIQUID")
|
||||
ss << ((mmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) ? "True" : "False");
|
||||
else if (varName == "USING_COLORS")
|
||||
if (varName == "USING_COLORS")
|
||||
ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_COLORS ? "True" : "False");
|
||||
else if (varName == "USING_HEAT")
|
||||
if (varName == "USING_HEAT")
|
||||
ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_HEAT ? "True" : "False");
|
||||
else if (varName == "USING_FIRE")
|
||||
if (varName == "USING_FIRE")
|
||||
ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_FIRE ? "True" : "False");
|
||||
else if (varName == "USING_NOISE")
|
||||
if (varName == "USING_NOISE")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_USE_NOISE ? "True" : "False");
|
||||
else if (varName == "USING_OBSTACLE")
|
||||
if (varName == "USING_OBSTACLE")
|
||||
ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE ? "True" : "False");
|
||||
else if (varName == "USING_GUIDING")
|
||||
if (varName == "USING_GUIDING")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_USE_GUIDE ? "True" : "False");
|
||||
else if (varName == "USING_INVEL")
|
||||
if (varName == "USING_INVEL")
|
||||
ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL ? "True" : "False");
|
||||
else if (varName == "USING_OUTFLOW")
|
||||
if (varName == "USING_OUTFLOW")
|
||||
ss << (mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW ? "True" : "False");
|
||||
else if (varName == "USING_LOG_DISSOLVE")
|
||||
if (varName == "USING_LOG_DISSOLVE")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DISSOLVE_LOG ? "True" : "False");
|
||||
else if (varName == "USING_DISSOLVE")
|
||||
if (varName == "USING_DISSOLVE")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DISSOLVE ? "True" : "False");
|
||||
else if (varName == "SOLVER_DIM")
|
||||
if (varName == "SOLVER_DIM")
|
||||
ss << mmd->domain->solver_res;
|
||||
else if (varName == "DO_OPEN") {
|
||||
if (varName == "DO_OPEN") {
|
||||
tmpVar = (FLUID_DOMAIN_BORDER_BACK | FLUID_DOMAIN_BORDER_FRONT | FLUID_DOMAIN_BORDER_LEFT |
|
||||
FLUID_DOMAIN_BORDER_RIGHT | FLUID_DOMAIN_BORDER_BOTTOM | FLUID_DOMAIN_BORDER_TOP);
|
||||
ss << (((mmd->domain->border_collisions & tmpVar) == tmpVar) ? "False" : "True");
|
||||
}
|
||||
else if (varName == "BOUND_CONDITIONS") {
|
||||
if (varName == "BOUND_CONDITIONS") {
|
||||
if (mmd->domain->solver_res == 2) {
|
||||
if ((mmd->domain->border_collisions & FLUID_DOMAIN_BORDER_LEFT) == 0)
|
||||
ss << "x";
|
||||
@@ -688,13 +690,13 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << "Z";
|
||||
}
|
||||
}
|
||||
else if (varName == "BOUNDARY_WIDTH")
|
||||
if (varName == "BOUNDARY_WIDTH")
|
||||
ss << mmd->domain->boundary_width;
|
||||
else if (varName == "RES")
|
||||
if (varName == "RES")
|
||||
ss << mMaxRes;
|
||||
else if (varName == "RESX")
|
||||
if (varName == "RESX")
|
||||
ss << mResX;
|
||||
else if (varName == "RESY")
|
||||
if (varName == "RESY")
|
||||
if (is2D) {
|
||||
ss << mResZ;
|
||||
}
|
||||
@@ -709,33 +711,35 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << mResZ;
|
||||
}
|
||||
}
|
||||
else if (varName == "FRAME_LENGTH")
|
||||
if (varName == "TIME_SCALE")
|
||||
ss << mmd->domain->time_scale;
|
||||
if (varName == "FRAME_LENGTH")
|
||||
ss << mmd->domain->frame_length;
|
||||
else if (varName == "CFL")
|
||||
if (varName == "CFL")
|
||||
ss << mmd->domain->cfl_condition;
|
||||
else if (varName == "DT")
|
||||
if (varName == "DT")
|
||||
ss << mmd->domain->dt;
|
||||
else if (varName == "TIMESTEPS_MIN")
|
||||
if (varName == "TIMESTEPS_MIN")
|
||||
ss << mmd->domain->timesteps_minimum;
|
||||
else if (varName == "TIMESTEPS_MAX")
|
||||
if (varName == "TIMESTEPS_MAX")
|
||||
ss << mmd->domain->timesteps_maximum;
|
||||
else if (varName == "TIME_TOTAL")
|
||||
if (varName == "TIME_TOTAL")
|
||||
ss << mmd->domain->time_total;
|
||||
else if (varName == "TIME_PER_FRAME")
|
||||
if (varName == "TIME_PER_FRAME")
|
||||
ss << mmd->domain->time_per_frame;
|
||||
else if (varName == "VORTICITY")
|
||||
if (varName == "VORTICITY")
|
||||
ss << mmd->domain->vorticity / mConstantScaling;
|
||||
else if (varName == "FLAME_VORTICITY")
|
||||
if (varName == "FLAME_VORTICITY")
|
||||
ss << mmd->domain->flame_vorticity / mConstantScaling;
|
||||
else if (varName == "NOISE_SCALE")
|
||||
if (varName == "NOISE_SCALE")
|
||||
ss << mmd->domain->noise_scale;
|
||||
else if (varName == "MESH_SCALE")
|
||||
if (varName == "MESH_SCALE")
|
||||
ss << mmd->domain->mesh_scale;
|
||||
else if (varName == "PARTICLE_SCALE")
|
||||
if (varName == "PARTICLE_SCALE")
|
||||
ss << mmd->domain->particle_scale;
|
||||
else if (varName == "NOISE_RESX")
|
||||
if (varName == "NOISE_RESX")
|
||||
ss << mResXNoise;
|
||||
else if (varName == "NOISE_RESY") {
|
||||
if (varName == "NOISE_RESY") {
|
||||
if (is2D) {
|
||||
ss << mResZNoise;
|
||||
}
|
||||
@@ -743,7 +747,7 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << mResYNoise;
|
||||
}
|
||||
}
|
||||
else if (varName == "NOISE_RESZ") {
|
||||
if (varName == "NOISE_RESZ") {
|
||||
if (is2D) {
|
||||
ss << 1;
|
||||
}
|
||||
@@ -751,9 +755,9 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << mResZNoise;
|
||||
}
|
||||
}
|
||||
else if (varName == "MESH_RESX")
|
||||
if (varName == "MESH_RESX")
|
||||
ss << mResXMesh;
|
||||
else if (varName == "MESH_RESY") {
|
||||
if (varName == "MESH_RESY") {
|
||||
if (is2D) {
|
||||
ss << mResZMesh;
|
||||
}
|
||||
@@ -761,7 +765,7 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << mResYMesh;
|
||||
}
|
||||
}
|
||||
else if (varName == "MESH_RESZ") {
|
||||
if (varName == "MESH_RESZ") {
|
||||
if (is2D) {
|
||||
ss << 1;
|
||||
}
|
||||
@@ -769,9 +773,9 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << mResZMesh;
|
||||
}
|
||||
}
|
||||
else if (varName == "PARTICLE_RESX")
|
||||
if (varName == "PARTICLE_RESX")
|
||||
ss << mResXParticle;
|
||||
else if (varName == "PARTICLE_RESY") {
|
||||
if (varName == "PARTICLE_RESY") {
|
||||
if (is2D) {
|
||||
ss << mResZParticle;
|
||||
}
|
||||
@@ -779,7 +783,7 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << mResYParticle;
|
||||
}
|
||||
}
|
||||
else if (varName == "PARTICLE_RESZ") {
|
||||
if (varName == "PARTICLE_RESZ") {
|
||||
if (is2D) {
|
||||
ss << 1;
|
||||
}
|
||||
@@ -787,9 +791,9 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << mResZParticle;
|
||||
}
|
||||
}
|
||||
else if (varName == "GUIDING_RESX")
|
||||
if (varName == "GUIDING_RESX")
|
||||
ss << mResGuiding[0];
|
||||
else if (varName == "GUIDING_RESY") {
|
||||
if (varName == "GUIDING_RESY") {
|
||||
if (is2D) {
|
||||
ss << mResGuiding[2];
|
||||
}
|
||||
@@ -797,7 +801,7 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << mResGuiding[1];
|
||||
}
|
||||
}
|
||||
else if (varName == "GUIDING_RESZ") {
|
||||
if (varName == "GUIDING_RESZ") {
|
||||
if (is2D) {
|
||||
ss << 1;
|
||||
}
|
||||
@@ -805,65 +809,65 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << mResGuiding[2];
|
||||
}
|
||||
}
|
||||
else if (varName == "MIN_RESX")
|
||||
if (varName == "MIN_RESX")
|
||||
ss << mmd->domain->res_min[0];
|
||||
else if (varName == "MIN_RESY")
|
||||
if (varName == "MIN_RESY")
|
||||
ss << mmd->domain->res_min[1];
|
||||
else if (varName == "MIN_RESZ")
|
||||
if (varName == "MIN_RESZ")
|
||||
ss << mmd->domain->res_min[2];
|
||||
else if (varName == "BASE_RESX")
|
||||
if (varName == "BASE_RESX")
|
||||
ss << mmd->domain->base_res[0];
|
||||
else if (varName == "BASE_RESY")
|
||||
if (varName == "BASE_RESY")
|
||||
ss << mmd->domain->base_res[1];
|
||||
else if (varName == "BASE_RESZ")
|
||||
if (varName == "BASE_RESZ")
|
||||
ss << mmd->domain->base_res[2];
|
||||
else if (varName == "WLT_STR")
|
||||
if (varName == "WLT_STR")
|
||||
ss << mmd->domain->noise_strength;
|
||||
else if (varName == "NOISE_POSSCALE")
|
||||
if (varName == "NOISE_POSSCALE")
|
||||
ss << mmd->domain->noise_pos_scale;
|
||||
else if (varName == "NOISE_TIMEANIM")
|
||||
if (varName == "NOISE_TIMEANIM")
|
||||
ss << mmd->domain->noise_time_anim;
|
||||
else if (varName == "COLOR_R")
|
||||
if (varName == "COLOR_R")
|
||||
ss << mmd->domain->active_color[0];
|
||||
else if (varName == "COLOR_G")
|
||||
if (varName == "COLOR_G")
|
||||
ss << mmd->domain->active_color[1];
|
||||
else if (varName == "COLOR_B")
|
||||
if (varName == "COLOR_B")
|
||||
ss << mmd->domain->active_color[2];
|
||||
else if (varName == "BUOYANCY_ALPHA")
|
||||
if (varName == "BUOYANCY_ALPHA")
|
||||
ss << mmd->domain->alpha;
|
||||
else if (varName == "BUOYANCY_BETA")
|
||||
if (varName == "BUOYANCY_BETA")
|
||||
ss << mmd->domain->beta;
|
||||
else if (varName == "DISSOLVE_SPEED")
|
||||
if (varName == "DISSOLVE_SPEED")
|
||||
ss << mmd->domain->diss_speed;
|
||||
else if (varName == "BURNING_RATE")
|
||||
if (varName == "BURNING_RATE")
|
||||
ss << mmd->domain->burning_rate;
|
||||
else if (varName == "FLAME_SMOKE")
|
||||
if (varName == "FLAME_SMOKE")
|
||||
ss << mmd->domain->flame_smoke;
|
||||
else if (varName == "IGNITION_TEMP")
|
||||
if (varName == "IGNITION_TEMP")
|
||||
ss << mmd->domain->flame_ignition;
|
||||
else if (varName == "MAX_TEMP")
|
||||
if (varName == "MAX_TEMP")
|
||||
ss << mmd->domain->flame_max_temp;
|
||||
else if (varName == "FLAME_SMOKE_COLOR_X")
|
||||
if (varName == "FLAME_SMOKE_COLOR_X")
|
||||
ss << mmd->domain->flame_smoke_color[0];
|
||||
else if (varName == "FLAME_SMOKE_COLOR_Y")
|
||||
if (varName == "FLAME_SMOKE_COLOR_Y")
|
||||
ss << mmd->domain->flame_smoke_color[1];
|
||||
else if (varName == "FLAME_SMOKE_COLOR_Z")
|
||||
if (varName == "FLAME_SMOKE_COLOR_Z")
|
||||
ss << mmd->domain->flame_smoke_color[2];
|
||||
else if (varName == "CURRENT_FRAME")
|
||||
if (varName == "CURRENT_FRAME")
|
||||
ss << mmd->time;
|
||||
else if (varName == "START_FRAME")
|
||||
if (varName == "START_FRAME")
|
||||
ss << mmd->domain->cache_frame_start;
|
||||
else if (varName == "END_FRAME")
|
||||
if (varName == "END_FRAME")
|
||||
ss << mmd->domain->cache_frame_end;
|
||||
else if (varName == "CACHE_DATA_FORMAT")
|
||||
if (varName == "CACHE_DATA_FORMAT")
|
||||
ss << getCacheFileEnding(mmd->domain->cache_data_format);
|
||||
else if (varName == "CACHE_MESH_FORMAT")
|
||||
if (varName == "CACHE_MESH_FORMAT")
|
||||
ss << getCacheFileEnding(mmd->domain->cache_mesh_format);
|
||||
else if (varName == "CACHE_NOISE_FORMAT")
|
||||
if (varName == "CACHE_NOISE_FORMAT")
|
||||
ss << getCacheFileEnding(mmd->domain->cache_noise_format);
|
||||
else if (varName == "CACHE_PARTICLE_FORMAT")
|
||||
if (varName == "CACHE_PARTICLE_FORMAT")
|
||||
ss << getCacheFileEnding(mmd->domain->cache_particle_format);
|
||||
else if (varName == "SIMULATION_METHOD") {
|
||||
if (varName == "SIMULATION_METHOD") {
|
||||
if (mmd->domain->simulation_method & FLUID_DOMAIN_METHOD_FLIP) {
|
||||
ss << "'FLIP'";
|
||||
}
|
||||
@@ -874,78 +878,78 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
ss << "'NONE'";
|
||||
}
|
||||
}
|
||||
else if (varName == "FLIP_RATIO")
|
||||
if (varName == "FLIP_RATIO")
|
||||
ss << mmd->domain->flip_ratio;
|
||||
else if (varName == "PARTICLE_RANDOMNESS")
|
||||
if (varName == "PARTICLE_RANDOMNESS")
|
||||
ss << mmd->domain->particle_randomness;
|
||||
else if (varName == "PARTICLE_NUMBER")
|
||||
if (varName == "PARTICLE_NUMBER")
|
||||
ss << mmd->domain->particle_number;
|
||||
else if (varName == "PARTICLE_MINIMUM")
|
||||
if (varName == "PARTICLE_MINIMUM")
|
||||
ss << mmd->domain->particle_minimum;
|
||||
else if (varName == "PARTICLE_MAXIMUM")
|
||||
if (varName == "PARTICLE_MAXIMUM")
|
||||
ss << mmd->domain->particle_maximum;
|
||||
else if (varName == "PARTICLE_RADIUS")
|
||||
if (varName == "PARTICLE_RADIUS")
|
||||
ss << mmd->domain->particle_radius;
|
||||
else if (varName == "FRACTIONS_THRESHOLD")
|
||||
if (varName == "FRACTIONS_THRESHOLD")
|
||||
ss << mmd->domain->fractions_threshold;
|
||||
else if (varName == "MESH_CONCAVE_UPPER")
|
||||
if (varName == "MESH_CONCAVE_UPPER")
|
||||
ss << mmd->domain->mesh_concave_upper;
|
||||
else if (varName == "MESH_CONCAVE_LOWER")
|
||||
if (varName == "MESH_CONCAVE_LOWER")
|
||||
ss << mmd->domain->mesh_concave_lower;
|
||||
else if (varName == "MESH_PARTICLE_RADIUS")
|
||||
if (varName == "MESH_PARTICLE_RADIUS")
|
||||
ss << mmd->domain->mesh_particle_radius;
|
||||
else if (varName == "MESH_SMOOTHEN_POS")
|
||||
if (varName == "MESH_SMOOTHEN_POS")
|
||||
ss << mmd->domain->mesh_smoothen_pos;
|
||||
else if (varName == "MESH_SMOOTHEN_NEG")
|
||||
if (varName == "MESH_SMOOTHEN_NEG")
|
||||
ss << mmd->domain->mesh_smoothen_neg;
|
||||
else if (varName == "USING_MESH")
|
||||
if (varName == "USING_MESH")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_USE_MESH ? "True" : "False");
|
||||
else if (varName == "USING_IMPROVED_MESH")
|
||||
if (varName == "USING_IMPROVED_MESH")
|
||||
ss << (mmd->domain->mesh_generator == FLUID_DOMAIN_MESH_IMPROVED ? "True" : "False");
|
||||
else if (varName == "PARTICLE_BAND_WIDTH")
|
||||
if (varName == "PARTICLE_BAND_WIDTH")
|
||||
ss << mmd->domain->particle_band_width;
|
||||
else if (varName == "SNDPARTICLE_TAU_MIN_WC")
|
||||
if (varName == "SNDPARTICLE_TAU_MIN_WC")
|
||||
ss << mmd->domain->sndparticle_tau_min_wc;
|
||||
else if (varName == "SNDPARTICLE_TAU_MAX_WC")
|
||||
if (varName == "SNDPARTICLE_TAU_MAX_WC")
|
||||
ss << mmd->domain->sndparticle_tau_max_wc;
|
||||
else if (varName == "SNDPARTICLE_TAU_MIN_TA")
|
||||
if (varName == "SNDPARTICLE_TAU_MIN_TA")
|
||||
ss << mmd->domain->sndparticle_tau_min_ta;
|
||||
else if (varName == "SNDPARTICLE_TAU_MAX_TA")
|
||||
if (varName == "SNDPARTICLE_TAU_MAX_TA")
|
||||
ss << mmd->domain->sndparticle_tau_max_ta;
|
||||
else if (varName == "SNDPARTICLE_TAU_MIN_K")
|
||||
if (varName == "SNDPARTICLE_TAU_MIN_K")
|
||||
ss << mmd->domain->sndparticle_tau_min_k;
|
||||
else if (varName == "SNDPARTICLE_TAU_MAX_K")
|
||||
if (varName == "SNDPARTICLE_TAU_MAX_K")
|
||||
ss << mmd->domain->sndparticle_tau_max_k;
|
||||
else if (varName == "SNDPARTICLE_K_WC")
|
||||
if (varName == "SNDPARTICLE_K_WC")
|
||||
ss << mmd->domain->sndparticle_k_wc;
|
||||
else if (varName == "SNDPARTICLE_K_TA")
|
||||
if (varName == "SNDPARTICLE_K_TA")
|
||||
ss << mmd->domain->sndparticle_k_ta;
|
||||
else if (varName == "SNDPARTICLE_K_B")
|
||||
if (varName == "SNDPARTICLE_K_B")
|
||||
ss << mmd->domain->sndparticle_k_b;
|
||||
else if (varName == "SNDPARTICLE_K_D")
|
||||
if (varName == "SNDPARTICLE_K_D")
|
||||
ss << mmd->domain->sndparticle_k_d;
|
||||
else if (varName == "SNDPARTICLE_L_MIN")
|
||||
if (varName == "SNDPARTICLE_L_MIN")
|
||||
ss << mmd->domain->sndparticle_l_min;
|
||||
else if (varName == "SNDPARTICLE_L_MAX")
|
||||
if (varName == "SNDPARTICLE_L_MAX")
|
||||
ss << mmd->domain->sndparticle_l_max;
|
||||
else if (varName == "SNDPARTICLE_BOUNDARY_DELETE")
|
||||
if (varName == "SNDPARTICLE_BOUNDARY_DELETE")
|
||||
ss << (mmd->domain->sndparticle_boundary == SNDPARTICLE_BOUNDARY_DELETE);
|
||||
else if (varName == "SNDPARTICLE_BOUNDARY_PUSHOUT")
|
||||
if (varName == "SNDPARTICLE_BOUNDARY_PUSHOUT")
|
||||
ss << (mmd->domain->sndparticle_boundary == SNDPARTICLE_BOUNDARY_PUSHOUT);
|
||||
else if (varName == "SNDPARTICLE_POTENTIAL_RADIUS")
|
||||
if (varName == "SNDPARTICLE_POTENTIAL_RADIUS")
|
||||
ss << mmd->domain->sndparticle_potential_radius;
|
||||
else if (varName == "SNDPARTICLE_UPDATE_RADIUS")
|
||||
if (varName == "SNDPARTICLE_UPDATE_RADIUS")
|
||||
ss << mmd->domain->sndparticle_update_radius;
|
||||
else if (varName == "LIQUID_SURFACE_TENSION")
|
||||
if (varName == "LIQUID_SURFACE_TENSION")
|
||||
ss << mmd->domain->surface_tension;
|
||||
else if (varName == "FLUID_VISCOSITY")
|
||||
if (varName == "FLUID_VISCOSITY")
|
||||
ss << mmd->domain->viscosity_base * pow(10.0f, -mmd->domain->viscosity_exponent);
|
||||
else if (varName == "FLUID_DOMAIN_SIZE") {
|
||||
if (varName == "FLUID_DOMAIN_SIZE") {
|
||||
tmpFloat = MAX3(
|
||||
mmd->domain->global_size[0], mmd->domain->global_size[1], mmd->domain->global_size[2]);
|
||||
ss << tmpFloat;
|
||||
}
|
||||
else if (varName == "SNDPARTICLE_TYPES") {
|
||||
if (varName == "SNDPARTICLE_TYPES") {
|
||||
if (mmd->domain->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY) {
|
||||
ss << "PtypeSpray";
|
||||
}
|
||||
@@ -967,38 +971,38 @@ std::string MANTA::getRealValue(const std::string &varName, FluidModifierData *m
|
||||
if (ss.str().empty())
|
||||
ss << "0";
|
||||
}
|
||||
else if (varName == "USING_SNDPARTS") {
|
||||
if (varName == "USING_SNDPARTS") {
|
||||
tmpVar = (FLUID_DOMAIN_PARTICLE_SPRAY | FLUID_DOMAIN_PARTICLE_BUBBLE |
|
||||
FLUID_DOMAIN_PARTICLE_FOAM | FLUID_DOMAIN_PARTICLE_TRACER);
|
||||
ss << (((mmd->domain->particle_type & tmpVar)) ? "True" : "False");
|
||||
}
|
||||
else if (varName == "GUIDING_ALPHA")
|
||||
if (varName == "GUIDING_ALPHA")
|
||||
ss << mmd->domain->guide_alpha;
|
||||
else if (varName == "GUIDING_BETA")
|
||||
if (varName == "GUIDING_BETA")
|
||||
ss << mmd->domain->guide_beta;
|
||||
else if (varName == "GUIDING_FACTOR")
|
||||
if (varName == "GUIDING_FACTOR")
|
||||
ss << mmd->domain->guide_vel_factor;
|
||||
else if (varName == "GRAVITY_X")
|
||||
if (varName == "GRAVITY_X")
|
||||
ss << mmd->domain->gravity[0];
|
||||
else if (varName == "GRAVITY_Y")
|
||||
if (varName == "GRAVITY_Y")
|
||||
ss << mmd->domain->gravity[1];
|
||||
else if (varName == "GRAVITY_Z")
|
||||
if (varName == "GRAVITY_Z")
|
||||
ss << mmd->domain->gravity[2];
|
||||
else if (varName == "CACHE_DIR")
|
||||
if (varName == "CACHE_DIR")
|
||||
ss << mmd->domain->cache_directory;
|
||||
else if (varName == "CACHE_RESUMABLE")
|
||||
if (varName == "CACHE_RESUMABLE")
|
||||
ss << (mmd->domain->cache_type == FLUID_DOMAIN_CACHE_FINAL ? "False" : "True");
|
||||
else if (varName == "USING_ADAPTIVETIME")
|
||||
if (varName == "USING_ADAPTIVETIME")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_USE_ADAPTIVE_TIME ? "True" : "False");
|
||||
else if (varName == "USING_SPEEDVECTORS")
|
||||
if (varName == "USING_SPEEDVECTORS")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_USE_SPEED_VECTORS ? "True" : "False");
|
||||
else if (varName == "USING_FRACTIONS")
|
||||
if (varName == "USING_FRACTIONS")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS ? "True" : "False");
|
||||
else if (varName == "DELETE_IN_OBSTACLE")
|
||||
if (varName == "DELETE_IN_OBSTACLE")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_DELETE_IN_OBSTACLE ? "True" : "False");
|
||||
else if (varName == "USING_DIFFUSION")
|
||||
if (varName == "USING_DIFFUSION")
|
||||
ss << (mmd->domain->flags & FLUID_DOMAIN_USE_DIFFUSION ? "True" : "False");
|
||||
else
|
||||
if (MANTA::with_debug && ss.str().empty())
|
||||
std::cerr << "Fluid Error -- Unknown option: " << varName << std::endl;
|
||||
return ss.str();
|
||||
}
|
||||
@@ -1078,8 +1082,7 @@ bool MANTA::updateFlipStructures(FluidModifierData *mmd, int framenr)
|
||||
assert(result == expected);
|
||||
}
|
||||
|
||||
mFlipFromFile = true;
|
||||
return (result == expected);
|
||||
return mFlipFromFile = (result == expected);
|
||||
}
|
||||
|
||||
bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr)
|
||||
@@ -1126,8 +1129,7 @@ bool MANTA::updateMeshStructures(FluidModifierData *mmd, int framenr)
|
||||
}
|
||||
}
|
||||
|
||||
mMeshFromFile = true;
|
||||
return (result == expected);
|
||||
return mMeshFromFile = (result == expected);
|
||||
}
|
||||
|
||||
bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr)
|
||||
@@ -1177,8 +1179,7 @@ bool MANTA::updateParticleStructures(FluidModifierData *mmd, int framenr)
|
||||
assert(result == expected);
|
||||
}
|
||||
|
||||
mParticlesFromFile = true;
|
||||
return (result == expected);
|
||||
return mParticlesFromFile = (result == expected);
|
||||
}
|
||||
|
||||
bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr)
|
||||
@@ -1268,8 +1269,7 @@ bool MANTA::updateSmokeStructures(FluidModifierData *mmd, int framenr)
|
||||
}
|
||||
}
|
||||
|
||||
mSmokeFromFile = true;
|
||||
return (result == expected);
|
||||
return mSmokeFromFile = (result == expected);
|
||||
}
|
||||
|
||||
bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr)
|
||||
@@ -1351,8 +1351,7 @@ bool MANTA::updateNoiseStructures(FluidModifierData *mmd, int framenr)
|
||||
}
|
||||
}
|
||||
|
||||
mNoiseFromFile = true;
|
||||
return (result == expected);
|
||||
return mNoiseFromFile = (result == expected);
|
||||
}
|
||||
|
||||
/* Dirty hack: Needed to format paths from python code that is run via PyRun_SimpleString */
|
||||
@@ -1930,6 +1929,7 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd)
|
||||
bool obstacle = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE;
|
||||
bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
|
||||
bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
|
||||
bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
|
||||
|
||||
std::string manta_script;
|
||||
|
||||
@@ -1972,6 +1972,8 @@ void MANTA::exportSmokeScript(FluidModifierData *mmd)
|
||||
manta_script += fluid_alloc_obstacle;
|
||||
if (invel)
|
||||
manta_script += fluid_alloc_invel;
|
||||
if (outflow)
|
||||
manta_script += fluid_alloc_outflow;
|
||||
|
||||
// Noise field
|
||||
if (noise)
|
||||
@@ -2036,6 +2038,7 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd)
|
||||
bool fractions = mmd->domain->flags & FLUID_DOMAIN_USE_FRACTIONS;
|
||||
bool guiding = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE;
|
||||
bool invel = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_INVEL;
|
||||
bool outflow = mmd->domain->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW;
|
||||
|
||||
std::string manta_script;
|
||||
|
||||
@@ -2074,6 +2077,8 @@ void MANTA::exportLiquidScript(FluidModifierData *mmd)
|
||||
manta_script += fluid_alloc_fractions;
|
||||
if (invel)
|
||||
manta_script += fluid_alloc_invel;
|
||||
if (outflow)
|
||||
manta_script += fluid_alloc_outflow;
|
||||
|
||||
// Domain init
|
||||
manta_script += header_gridinit + liquid_init_phi;
|
||||
@@ -2748,10 +2753,10 @@ bool MANTA::updateParticlesFromUni(std::string filename, bool isSecondarySys, bo
|
||||
return false;
|
||||
}
|
||||
if (!ibuffer[0]) { // Any particles present?
|
||||
std::cerr << "Fluid Error -- updateParticlesFromUni(): No particles present in file: "
|
||||
<< filename << std::endl;
|
||||
if (with_debug)
|
||||
std::cout << "Fluid: No particles present in file: " << filename << std::endl;
|
||||
gzclose(gzf);
|
||||
return false;
|
||||
return true; // return true since having no particles in a cache file is valid
|
||||
}
|
||||
|
||||
numParticles = ibuffer[0];
|
||||
@@ -3123,6 +3128,8 @@ void MANTA::updatePointers()
|
||||
|
||||
if (mUsingOutflow) {
|
||||
mPhiOutIn = (float *)pyObjectToPointer(callPythonFunction("phiOutIn" + solver_ext, func));
|
||||
mPhiOutStaticIn = (float *)pyObjectToPointer(
|
||||
callPythonFunction("phiOutSIn" + solver_ext, func));
|
||||
}
|
||||
if (mUsingObstacle) {
|
||||
mPhiObsIn = (float *)pyObjectToPointer(callPythonFunction("phiObsIn" + solver_ext, func));
|
||||
@@ -3234,7 +3241,7 @@ bool MANTA::hasConfig(FluidModifierData *mmd, int framenr)
|
||||
|
||||
bool MANTA::hasData(FluidModifierData *mmd, int framenr)
|
||||
{
|
||||
std::string filename = (mUsingSmoke) ? FLUID_DOMAIN_FILE_DENSITY : FLUID_DOMAIN_FILE_PHI;
|
||||
std::string filename = (mUsingSmoke) ? FLUID_DOMAIN_FILE_DENSITY : FLUID_DOMAIN_FILE_PP;
|
||||
std::string extension = getCacheFileEnding(mmd->domain->cache_data_format);
|
||||
return BLI_exists(getFile(mmd, FLUID_DOMAIN_DIR_DATA, filename, extension, framenr).c_str());
|
||||
}
|
||||
|
@@ -405,6 +405,10 @@ struct MANTA {
|
||||
{
|
||||
return mPhiOutIn;
|
||||
}
|
||||
inline float *getPhiOutStaticIn()
|
||||
{
|
||||
return mPhiOutStaticIn;
|
||||
}
|
||||
inline float *getPhi()
|
||||
{
|
||||
return mPhi;
|
||||
@@ -844,6 +848,7 @@ struct MANTA {
|
||||
float *mPhiObsStaticIn;
|
||||
float *mPhiGuideIn;
|
||||
float *mPhiOutIn;
|
||||
float *mPhiOutStaticIn;
|
||||
float *mPhi;
|
||||
|
||||
// Mesh fields
|
||||
|
@@ -390,6 +390,10 @@ float *manta_get_phiout_in(MANTA *fluid)
|
||||
{
|
||||
return fluid->getPhiOutIn();
|
||||
}
|
||||
float *manta_get_phioutstatic_in(MANTA *fluid)
|
||||
{
|
||||
return fluid->getPhiOutStaticIn();
|
||||
}
|
||||
|
||||
/* Smoke functions */
|
||||
void manta_smoke_export_script(MANTA *smoke, FluidModifierData *mmd)
|
||||
|
@@ -92,7 +92,7 @@ const std::string fluid_variables =
|
||||
mantaMsg('Fluid variables')\n\
|
||||
dim_s$ID$ = $SOLVER_DIM$\n\
|
||||
res_s$ID$ = $RES$\n\
|
||||
gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$)\n\
|
||||
gravity_s$ID$ = vec3($GRAVITY_X$, $GRAVITY_Y$, $GRAVITY_Z$) # in SI unit (e.g. m/s^2)\n\
|
||||
gs_s$ID$ = vec3($RESX$, $RESY$, $RESZ$)\n\
|
||||
maxVel_s$ID$ = 0\n\
|
||||
\n\
|
||||
@@ -115,6 +115,7 @@ using_speedvectors_s$ID$ = $USING_SPEEDVECTORS$\n\
|
||||
using_diffusion_s$ID$ = $USING_DIFFUSION$\n\
|
||||
\n\
|
||||
# Fluid time params\n\
|
||||
timeScale_s$ID$ = $TIME_SCALE$\n\
|
||||
timeTotal_s$ID$ = $TIME_TOTAL$\n\
|
||||
timePerFrame_s$ID$ = $TIME_PER_FRAME$\n\
|
||||
frameLength_s$ID$ = $FRAME_LENGTH$\n\
|
||||
@@ -132,8 +133,29 @@ end_frame_s$ID$ = $END_FRAME$\n\
|
||||
domainSize_s$ID$ = $FLUID_DOMAIN_SIZE$ # longest domain side in meters\n\
|
||||
viscosity_s$ID$ = $FLUID_VISCOSITY$ / (domainSize_s$ID$*domainSize_s$ID$) # kinematic viscosity in m^2/s\n\
|
||||
\n\
|
||||
# Factor to convert blender velocities to manta velocities\n\
|
||||
toMantaUnitsFac_s$ID$ = (1.0 / (1.0 / res_s$ID$))\n # = dt/dx * 1/dt ";
|
||||
# Factors to convert Blender units to Manta units\n\
|
||||
ratioMetersToRes_s$ID$ = float(domainSize_s$ID$) / float(res_s$ID$) # [meters / cells]\n\
|
||||
mantaMsg('1 Mantaflow cell is ' + str(ratioMetersToRes_s$ID$) + ' Blender length units long.')\n\
|
||||
\n\
|
||||
ratioResToBLength_s$ID$ = float(res_s$ID$) / float(domainSize_s$ID$) # [cells / blength] (blength: cm, m, or km, ... )\n\
|
||||
mantaMsg('1 Blender length unit is ' + str(ratioResToBLength_s$ID$) + ' Mantaflow cells long.')\n\
|
||||
\n\
|
||||
ratioBTimeToTimstep_s$ID$ = float(1) / float(0.1 * 25 * timeScale_s$ID$) # the time within 1 blender time unit, see also fluid.c\n\
|
||||
mantaMsg('1 Blender time unit is ' + str(ratioBTimeToTimstep_s$ID$) + ' Mantaflow time units long.')\n\
|
||||
\n\
|
||||
ratioFrameToFramelength_s$ID$ = float(1) / float(frameLength_s$ID$) # the time within 1 frame\n\
|
||||
mantaMsg('frame / frameLength is ' + str(ratioFrameToFramelength_s$ID$) + ' Mantaflow time units long.')\n\
|
||||
\n\
|
||||
scaleAcceleration_s$ID$ = ratioResToBLength_s$ID$ * (ratioBTimeToTimstep_s$ID$**2)# [meters/btime^2] to [cells/timestep^2] (btime: sec, min, or h, ...)\n\
|
||||
mantaMsg('scaleAcceleration is ' + str(scaleAcceleration_s$ID$))\n\
|
||||
\n\
|
||||
scaleSpeedFrames_s$ID$ = ratioResToBLength_s$ID$ * ratioFrameToFramelength_s$ID$ # [blength/frame] to [cells/frameLength]\n\
|
||||
mantaMsg('scaleSpeed is ' + str(scaleSpeedFrames_s$ID$))\n\
|
||||
\n\
|
||||
scaleSpeedTime_s$ID$ = ratioResToBLength_s$ID$ * ratioBTimeToTimstep_s$ID$ # [blength/btime] to [cells/frameLength]\n\
|
||||
mantaMsg('scaleSpeedTime is ' + str(scaleSpeedTime_s$ID$))\n\
|
||||
\n\
|
||||
gravity_s$ID$ *= scaleAcceleration_s$ID$ # scale from world acceleration to cell based acceleration\n";
|
||||
|
||||
const std::string fluid_variables_noise =
|
||||
"\n\
|
||||
@@ -261,7 +283,7 @@ const std::string fluid_alloc_obstacle =
|
||||
"\n\
|
||||
mantaMsg('Allocating obstacle data')\n\
|
||||
numObs_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
phiObsSIn_s$ID$ = s$ID$.create(LevelsetGrid) # helper for static obstacles\n\
|
||||
phiObsSIn_s$ID$ = s$ID$.create(LevelsetGrid) # helper for static obstacle objects\n\
|
||||
phiObsIn_s$ID$ = s$ID$.create(LevelsetGrid)\n\
|
||||
obvel_s$ID$ = s$ID$.create(MACGrid)\n\
|
||||
obvelC_s$ID$ = s$ID$.create(Vec3Grid)\n\
|
||||
@@ -311,7 +333,15 @@ z_invel_s$ID$ = s$ID$.create(RealGrid)\n";
|
||||
const std::string fluid_alloc_outflow =
|
||||
"\n\
|
||||
mantaMsg('Allocating outflow data')\n\
|
||||
phiOutIn_s$ID$ = s$ID$.create(LevelsetGrid)\n";
|
||||
phiOutSIn_s$ID$ = s$ID$.create(LevelsetGrid) # helper for static outflow objects\n\
|
||||
phiOutIn_s$ID$ = s$ID$.create(LevelsetGrid)\n\
|
||||
\n\
|
||||
# Set some initial values\n\
|
||||
phiOutSIn_s$ID$.setConst(9999)\n\
|
||||
phiOutIn_s$ID$.setConst(9999)\n\
|
||||
\n\
|
||||
if 'fluid_data_dict_resume_s$ID$' in globals():\n\
|
||||
fluid_data_dict_resume_s$ID$.update(phiOutIn=phiOutIn_s$ID$)\n";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// PRE / POST STEP
|
||||
@@ -334,17 +364,16 @@ def fluid_pre_step_$ID$():\n\
|
||||
y_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\
|
||||
z_obvel_s$ID$.safeDivide(numObs_s$ID$)\n\
|
||||
\n\
|
||||
x_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
|
||||
y_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
|
||||
z_obvel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
|
||||
\n\
|
||||
x_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
|
||||
y_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
|
||||
z_obvel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
|
||||
copyRealToVec3(sourceX=x_obvel_s$ID$, sourceY=y_obvel_s$ID$, sourceZ=z_obvel_s$ID$, target=obvelC_s$ID$)\n\
|
||||
\n\
|
||||
# translate invels (world space) to grid space\n\
|
||||
if using_invel_s$ID$:\n\
|
||||
x_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
|
||||
y_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
|
||||
z_invel_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
|
||||
x_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\
|
||||
y_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\
|
||||
z_invel_s$ID$.multConst(scaleSpeedTime_s$ID$)\n\
|
||||
copyRealToVec3(sourceX=x_invel_s$ID$, sourceY=y_invel_s$ID$, sourceZ=z_invel_s$ID$, target=invelC_s$ID$)\n\
|
||||
\n\
|
||||
if using_guiding_s$ID$:\n\
|
||||
@@ -354,9 +383,9 @@ def fluid_pre_step_$ID$():\n\
|
||||
velT_s$ID$.multConst(vec3(gamma_sg$ID$))\n\
|
||||
\n\
|
||||
# translate external forces (world space) to grid space\n\
|
||||
x_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
|
||||
y_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
|
||||
z_force_s$ID$.multConst(toMantaUnitsFac_s$ID$)\n\
|
||||
x_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
|
||||
y_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
|
||||
z_force_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
|
||||
copyRealToVec3(sourceX=x_force_s$ID$, sourceY=y_force_s$ID$, sourceZ=z_force_s$ID$, target=forces_s$ID$)\n\
|
||||
\n\
|
||||
# If obstacle has velocity, i.e. is a moving obstacle, switch to dynamic preconditioner\n\
|
||||
@@ -527,7 +556,6 @@ def bake_noise_process_$ID$(framenr, format_data, format_noise, path_data, path_
|
||||
sn$ID$.timestep = frameLength_s$ID$ # no adaptive timestep for noise\n\
|
||||
\n\
|
||||
smoke_step_noise_$ID$(framenr)\n\
|
||||
smoke_save_noise_$ID$(path_noise, framenr, format_noise, resumable)\n\
|
||||
\n\
|
||||
def bake_noise_$ID$(path_data, path_noise, framenr, format_data, format_noise, resumable):\n\
|
||||
if not withMPBake or isWindows:\n\
|
||||
@@ -591,10 +619,9 @@ def bake_guiding_process_$ID$(framenr, format_guiding, path_guiding, resumable):
|
||||
y_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\
|
||||
z_guidevel_s$ID$.safeDivide(numGuides_s$ID$)\n\
|
||||
\n\
|
||||
x_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\
|
||||
y_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\
|
||||
z_guidevel_s$ID$.multConst(Real(toMantaUnitsFac_s$ID$))\n\
|
||||
\n\
|
||||
x_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
|
||||
y_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
|
||||
z_guidevel_s$ID$.multConst(scaleSpeedFrames_s$ID$)\n\
|
||||
copyRealToVec3(sourceX=x_guidevel_s$ID$, sourceY=y_guidevel_s$ID$, sourceZ=z_guidevel_s$ID$, target=guidevelC_s$ID$)\n\
|
||||
\n\
|
||||
mantaMsg('Extrapolating guiding velocity')\n\
|
||||
|
@@ -67,8 +67,7 @@ lMax_sp$ID$ = $SNDPARTICLE_L_MAX$\n\
|
||||
c_s_sp$ID$ = 0.4 # classification constant for snd parts\n\
|
||||
c_b_sp$ID$ = 0.77 # classification constant for snd parts\n\
|
||||
pot_radius_sp$ID$ = $SNDPARTICLE_POTENTIAL_RADIUS$\n\
|
||||
update_radius_sp$ID$ = $SNDPARTICLE_UPDATE_RADIUS$\n\
|
||||
scaleFromManta_sp$ID$ = $FLUID_DOMAIN_SIZE$ / float(res_s$ID$) # resize factor for snd parts\n";
|
||||
update_radius_sp$ID$ = $SNDPARTICLE_UPDATE_RADIUS$\n";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// GRIDS & MESH & PARTICLESYSTEM
|
||||
@@ -173,14 +172,14 @@ def liquid_adaptive_step_$ID$(framenr):\n\
|
||||
if using_obstacle_s$ID$:\n\
|
||||
mantaMsg('Initializing obstacle levelset')\n\
|
||||
phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
|
||||
phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
|
||||
phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=1)\n\
|
||||
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
|
||||
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
|
||||
phiObs_s$ID$.join(phiObsIn_s$ID$)\n\
|
||||
\n\
|
||||
# Using boundaryWidth=2 to not search beginning from walls (just a performance optimization)\n\
|
||||
# Additional sanity check: fill holes in phiObs which can result after joining with phiObsIn\n\
|
||||
phiObs_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
|
||||
phiObs_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2 if using_fractions_s$ID$ else 1)\n\
|
||||
extrapolateLsSimple(phi=phiObs_s$ID$, distance=6, inside=True)\n\
|
||||
extrapolateLsSimple(phi=phiObs_s$ID$, distance=3)\n\
|
||||
\n\
|
||||
@@ -191,6 +190,7 @@ def liquid_adaptive_step_$ID$(framenr):\n\
|
||||
phi_s$ID$.join(phiIn_s$ID$)\n\
|
||||
\n\
|
||||
if using_outflow_s$ID$:\n\
|
||||
phiOutIn_s$ID$.join(phiOutSIn_s$ID$) # Join static outflow map\n\
|
||||
phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
|
||||
\n\
|
||||
if using_fractions_s$ID$:\n\
|
||||
@@ -206,6 +206,9 @@ def liquid_adaptive_step_$ID$(framenr):\n\
|
||||
extrapolateVec3Simple(vel=invelC_s$ID$, phi=phiIn_s$ID$, distance=6, inside=True)\n\
|
||||
resampleVec3ToMac(source=invelC_s$ID$, target=invel_s$ID$)\n\
|
||||
pVel_pp$ID$.setSource(invel_s$ID$, isMAC=True)\n\
|
||||
# ensure that pvel has vel as source (important when resuming bake jobs)\n\
|
||||
else:\n\
|
||||
pVel_pp$ID$.setSource(vel_s$ID$, isMAC=True)\n\
|
||||
\n\
|
||||
sampleLevelsetWithParticles(phi=phiIn_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, discretization=particleNumber_s$ID$, randomness=randomness_s$ID$)\n\
|
||||
flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
|
||||
@@ -259,7 +262,7 @@ def liquid_step_$ID$():\n\
|
||||
velOld_s$ID$.copyFrom(vel_s$ID$)\n\
|
||||
\n\
|
||||
# forces & pressure solve\n\
|
||||
addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$)\n\
|
||||
addGravity(flags=flags_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, scale=False)\n\
|
||||
\n\
|
||||
mantaMsg('Adding external forces')\n\
|
||||
addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\
|
||||
@@ -363,11 +366,11 @@ def liquid_step_particles_$ID$():\n\
|
||||
interpolateGrid(target=phiOut_sp$ID$, source=phiOut_s$ID$)\n\
|
||||
\n\
|
||||
# phiIn not needed, bwidth to 0 because we are omitting flags.initDomain()\n\
|
||||
setObstacleFlags(flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, phiOut=None, phiIn=None, boundaryWidth=0)\n\
|
||||
setObstacleFlags(flags=flags_sp$ID$, phiObs=phiObs_sp$ID$, phiOut=phiOut_sp$ID$, phiIn=None, boundaryWidth=0)\n\
|
||||
flags_sp$ID$.updateFromLevelset(levelset=phi_sp$ID$)\n\
|
||||
\n\
|
||||
# Actual secondary particle simulation\n\
|
||||
flipComputeSecondaryParticlePotentials(potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, normal=normal_sp$ID$, phi=phi_sp$ID$, radius=pot_radius_sp$ID$, tauMinTA=tauMin_ta_sp$ID$, tauMaxTA=tauMax_ta_sp$ID$, tauMinWC=tauMin_wc_sp$ID$, tauMaxWC=tauMax_wc_sp$ID$, tauMinKE=tauMin_k_sp$ID$, tauMaxKE=tauMax_k_sp$ID$, scaleFromManta=scaleFromManta_sp$ID$)\n\
|
||||
flipComputeSecondaryParticlePotentials(potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, normal=normal_sp$ID$, phi=phi_sp$ID$, radius=pot_radius_sp$ID$, tauMinTA=tauMin_ta_sp$ID$, tauMaxTA=tauMax_ta_sp$ID$, tauMinWC=tauMin_wc_sp$ID$, tauMaxWC=tauMax_wc_sp$ID$, tauMinKE=tauMin_k_sp$ID$, tauMaxKE=tauMax_k_sp$ID$, scaleFromManta=ratioMetersToRes_s$ID$)\n\
|
||||
flipSampleSecondaryParticles(mode='single', flags=flags_sp$ID$, v=vel_sp$ID$, pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, lMin=lMin_sp$ID$, lMax=lMax_sp$ID$, potTA=trappedAir_sp$ID$, potWC=waveCrest_sp$ID$, potKE=kineticEnergy_sp$ID$, neighborRatio=neighborRatio_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, k_ta=k_ta_sp$ID$, k_wc=k_wc_sp$ID$, dt=sp$ID$.timestep)\n\
|
||||
flipUpdateSecondaryParticles(mode='linear', pts_sec=ppSnd_sp$ID$, v_sec=pVelSnd_pp$ID$, l_sec=pLifeSnd_pp$ID$, f_sec=pForceSnd_pp$ID$, flags=flags_sp$ID$, v=vel_sp$ID$, neighborRatio=neighborRatio_sp$ID$, radius=update_radius_sp$ID$, gravity=gravity_s$ID$, k_b=k_b_sp$ID$, k_d=k_d_sp$ID$, c_s=c_s_sp$ID$, c_b=c_b_sp$ID$, dt=sp$ID$.timestep)\n\
|
||||
if $SNDPARTICLE_BOUNDARY_PUSHOUT$:\n\
|
||||
|
@@ -279,14 +279,14 @@ def smoke_adaptive_step_$ID$(framenr):\n\
|
||||
if using_obstacle_s$ID$:\n\
|
||||
mantaMsg('Initializing obstacle levelset')\n\
|
||||
phiObsIn_s$ID$.join(phiObsSIn_s$ID$) # Join static obstacle map\n\
|
||||
phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
|
||||
phiObsIn_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=1)\n\
|
||||
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=6, inside=True)\n\
|
||||
extrapolateLsSimple(phi=phiObsIn_s$ID$, distance=3, inside=False)\n\
|
||||
phiObs_s$ID$.join(phiObsIn_s$ID$)\n\
|
||||
\n\
|
||||
# Using boundaryWidth=2 to not search beginning from walls (just a performance optimization)\n\
|
||||
# Additional sanity check: fill holes in phiObs which can result after joining with phiObsIn\n\
|
||||
phiObs_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=2)\n\
|
||||
phiObs_s$ID$.fillHoles(maxDepth=int(res_s$ID$), boundaryWidth=1)\n\
|
||||
extrapolateLsSimple(phi=phiObs_s$ID$, distance=6, inside=True)\n\
|
||||
extrapolateLsSimple(phi=phiObs_s$ID$, distance=3, inside=False)\n\
|
||||
\n\
|
||||
@@ -296,11 +296,15 @@ def smoke_adaptive_step_$ID$(framenr):\n\
|
||||
extrapolateLsSimple(phi=phiIn_s$ID$, distance=3, inside=False)\n\
|
||||
\n\
|
||||
if using_outflow_s$ID$:\n\
|
||||
phiOutIn_s$ID$.join(phiOutSIn_s$ID$) # Join static outflow map\n\
|
||||
phiOut_s$ID$.join(phiOutIn_s$ID$)\n\
|
||||
\n\
|
||||
setObstacleFlags(flags=flags_s$ID$, phiObs=phiObs_s$ID$, phiOut=phiOut_s$ID$, phiIn=phiIn_s$ID$, boundaryWidth=1)\n\
|
||||
flags_s$ID$.fillGrid()\n\
|
||||
\n\
|
||||
# reset emission accumulation at the beginning of an adaptive frame\n\
|
||||
if not s$ID$.timePerFrame:\n\
|
||||
emission_s$ID$.setConst(0.)\n\
|
||||
# accumulate emission value per adaptive step for later use in noise computation\n\
|
||||
emission_s$ID$.join(emissionIn_s$ID$)\n\
|
||||
\n\
|
||||
@@ -372,9 +376,9 @@ def smoke_step_$ID$():\n\
|
||||
\n\
|
||||
if using_heat_s$ID$:\n\
|
||||
mantaMsg('Adding heat buoyancy')\n\
|
||||
addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$)\n\
|
||||
addBuoyancy(flags=flags_s$ID$, density=heat_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_heat_s$ID$, scale=False)\n\
|
||||
mantaMsg('Adding buoyancy')\n\
|
||||
addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$)\n\
|
||||
addBuoyancy(flags=flags_s$ID$, density=density_s$ID$, vel=vel_s$ID$, gravity=gravity_s$ID$, coefficient=buoyancy_dens_s$ID$, scale=False)\n\
|
||||
\n\
|
||||
mantaMsg('Adding forces')\n\
|
||||
addForceField(flags=flags_s$ID$, vel=vel_s$ID$, force=forces_s$ID$)\n\
|
||||
|
@@ -173,18 +173,27 @@ inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
|
||||
setBaseVertexSharpness(refiner, vertex_index, Crease::SHARPNESS_INFINITE);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get sharpness provided by the converter.
|
||||
float sharpness = 0.0f;
|
||||
if (converter->getVertexSharpness != NULL) {
|
||||
float sharpness = converter->getVertexSharpness(converter, vertex_index);
|
||||
if (vertex_edges.size() == 2) {
|
||||
const int edge0 = vertex_edges[0], edge1 = vertex_edges[1];
|
||||
const float sharpness0 = refiner._levels[0]->getEdgeSharpness(edge0);
|
||||
const float sharpness1 = refiner._levels[0]->getEdgeSharpness(edge1);
|
||||
// TODO(sergey): Find a better mixing between edge and vertex sharpness.
|
||||
sharpness += min(sharpness0, sharpness1);
|
||||
sharpness = min(sharpness, 10.0f);
|
||||
}
|
||||
setBaseVertexSharpness(refiner, vertex_index, sharpness);
|
||||
sharpness = converter->getVertexSharpness(converter, vertex_index);
|
||||
}
|
||||
|
||||
// If it's vertex where 2 non-manifold edges meet adjust vertex sharpness to
|
||||
// the edges.
|
||||
// This way having a plane with all 4 edges set to be sharp produces sharp
|
||||
// corners in the subdivided result.
|
||||
if (vertex_edges.size() == 2) {
|
||||
const int edge0 = vertex_edges[0], edge1 = vertex_edges[1];
|
||||
const float sharpness0 = refiner._levels[0]->getEdgeSharpness(edge0);
|
||||
const float sharpness1 = refiner._levels[0]->getEdgeSharpness(edge1);
|
||||
// TODO(sergey): Find a better mixing between edge and vertex sharpness.
|
||||
sharpness += min(sharpness0, sharpness1);
|
||||
sharpness = min(sharpness, 10.0f);
|
||||
}
|
||||
|
||||
setBaseVertexSharpness(refiner, vertex_index, sharpness);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -1,366 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup string
|
||||
*/
|
||||
|
||||
#ifndef __STR_STRING_H__
|
||||
#define __STR_STRING_H__
|
||||
|
||||
#ifndef STR_NO_ASSERTD
|
||||
# undef assertd
|
||||
# define assertd(exp) ((void)NULL)
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <vector>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
# include "MEM_guardedalloc.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define stricmp _stricmp
|
||||
#endif
|
||||
|
||||
class STR_String;
|
||||
|
||||
typedef unsigned long dword;
|
||||
typedef const STR_String &rcSTR_String;
|
||||
typedef unsigned char byte;
|
||||
|
||||
/**
|
||||
* Smart String Value class. Is used by parser when an expression tree is build containing string.
|
||||
*/
|
||||
|
||||
class STR_String {
|
||||
public:
|
||||
// Initialization
|
||||
STR_String();
|
||||
STR_String(char c);
|
||||
STR_String(char c, int len);
|
||||
STR_String(const char *str);
|
||||
STR_String(const char *str, int len);
|
||||
STR_String(const STR_String &str);
|
||||
STR_String(const STR_String &str, int len);
|
||||
STR_String(const char *src1, int src1_len, const char *src2, int src2_len);
|
||||
explicit STR_String(int val);
|
||||
explicit STR_String(dword val);
|
||||
explicit STR_String(float val);
|
||||
explicit STR_String(double val);
|
||||
inline ~STR_String()
|
||||
{
|
||||
delete[] this->m_data;
|
||||
}
|
||||
|
||||
// Operations
|
||||
STR_String &Format(const char *fmt, ...) // Set formatted text to string
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
STR_String &FormatAdd(const char *fmt, ...) // Add formatted text to string
|
||||
#ifdef __GNUC__
|
||||
__attribute__((format(printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
inline void Clear()
|
||||
{
|
||||
this->m_len = this->m_data[0] = 0;
|
||||
}
|
||||
inline const STR_String &Reverse()
|
||||
{
|
||||
for (int i1 = 0, i2 = this->m_len - 1; i1 < i2; i1++, i2--) {
|
||||
std::swap(this->m_data[i1], this->m_data[i2]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Properties
|
||||
bool IsUpper() const;
|
||||
bool IsLower() const;
|
||||
inline bool IsEmpty() const
|
||||
{
|
||||
return this->m_len == 0;
|
||||
}
|
||||
inline int Length() const
|
||||
{
|
||||
return this->m_len;
|
||||
}
|
||||
|
||||
// Data access
|
||||
inline STR_String &SetLength(int len)
|
||||
{
|
||||
AllocBuffer(len, true);
|
||||
this->m_len = len;
|
||||
this->m_data[len] = 0;
|
||||
return *this;
|
||||
}
|
||||
inline char GetAt(int pos) const
|
||||
{
|
||||
assertd(pos < this->m_len);
|
||||
return this->m_data[pos];
|
||||
}
|
||||
inline void SetAt(int pos, char c)
|
||||
{
|
||||
assertd(pos < this->m_len);
|
||||
this->m_data[pos] = c;
|
||||
}
|
||||
inline void SetAt(int pos, rcSTR_String str);
|
||||
inline void SetAt(int pos, int num, rcSTR_String str);
|
||||
void Replace(int pos, rcSTR_String str);
|
||||
void Replace(int pos, int num, rcSTR_String str);
|
||||
|
||||
// Substrings
|
||||
inline STR_String Left(int num) const
|
||||
{
|
||||
num = (num < this->m_len ? num : this->m_len);
|
||||
return STR_String(this->m_data, num);
|
||||
}
|
||||
inline STR_String Right(int num) const
|
||||
{
|
||||
num = (num < this->m_len ? num : this->m_len);
|
||||
return STR_String(this->m_data + this->m_len - num, num);
|
||||
}
|
||||
inline STR_String Mid(int pos, int num = INT_MAX) const
|
||||
{
|
||||
pos = (pos < this->m_len ? pos : this->m_len);
|
||||
num = (num < (this->m_len - pos) ? num : (this->m_len - pos));
|
||||
return STR_String(this->m_data + pos, num);
|
||||
}
|
||||
|
||||
// Comparison
|
||||
int Compare(rcSTR_String rhs) const;
|
||||
int CompareNoCase(rcSTR_String rhs) const;
|
||||
inline bool IsEqual(rcSTR_String rhs) const
|
||||
{
|
||||
return (Compare(rhs) == 0);
|
||||
}
|
||||
inline bool IsEqualNoCase(rcSTR_String rhs) const
|
||||
{
|
||||
return (CompareNoCase(rhs) == 0);
|
||||
}
|
||||
|
||||
// Search/replace
|
||||
int Find(char c, int pos = 0) const;
|
||||
int Find(const char *str, int pos = 0) const;
|
||||
int Find(rcSTR_String str, int pos = 0) const;
|
||||
int RFind(char c) const;
|
||||
int FindOneOf(const char *set, int pos = 0) const;
|
||||
int RFindOneOf(const char *set, int pos = 0) const;
|
||||
|
||||
std::vector<STR_String> Explode(char c) const;
|
||||
|
||||
// Formatting
|
||||
STR_String &Upper();
|
||||
STR_String &Lower();
|
||||
STR_String &Capitalize();
|
||||
STR_String &TrimLeft();
|
||||
STR_String &TrimLeft(char *set);
|
||||
STR_String &TrimRight();
|
||||
STR_String &TrimRight(char *set);
|
||||
STR_String &Trim();
|
||||
STR_String &Trim(char *set);
|
||||
STR_String &TrimQuotes();
|
||||
|
||||
// Conversions
|
||||
// inline operator char*() { return this->m_data; }
|
||||
inline operator const char *() const
|
||||
{
|
||||
return this->m_data;
|
||||
}
|
||||
inline char *Ptr()
|
||||
{
|
||||
return this->m_data;
|
||||
}
|
||||
inline const char *ReadPtr() const
|
||||
{
|
||||
return this->m_data;
|
||||
}
|
||||
inline float ToFloat() const
|
||||
{
|
||||
float x = (float)(atof(this->m_data));
|
||||
return x;
|
||||
}
|
||||
inline int ToInt() const
|
||||
{
|
||||
return atoi(this->m_data);
|
||||
}
|
||||
|
||||
// Operators
|
||||
inline rcSTR_String operator=(const byte *rhs)
|
||||
{
|
||||
return Copy((const char *)rhs, strlen((const char *)rhs));
|
||||
}
|
||||
inline rcSTR_String operator=(rcSTR_String rhs)
|
||||
{
|
||||
return Copy(rhs.ReadPtr(), rhs.Length());
|
||||
}
|
||||
inline rcSTR_String operator=(char rhs)
|
||||
{
|
||||
return Copy(&rhs, 1);
|
||||
}
|
||||
inline rcSTR_String operator=(const char *rhs)
|
||||
{
|
||||
return Copy(rhs, strlen(rhs));
|
||||
}
|
||||
|
||||
inline rcSTR_String operator+=(const char *rhs)
|
||||
{
|
||||
return Concat(rhs, strlen(rhs));
|
||||
}
|
||||
inline rcSTR_String operator+=(rcSTR_String rhs)
|
||||
{
|
||||
return Concat(rhs.ReadPtr(), rhs.Length());
|
||||
}
|
||||
inline rcSTR_String operator+=(char rhs)
|
||||
{
|
||||
return Concat(&rhs, 1);
|
||||
}
|
||||
|
||||
inline friend bool operator<(rcSTR_String lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) < 0);
|
||||
}
|
||||
inline friend bool operator<(rcSTR_String lhs, const char *rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) < 0);
|
||||
}
|
||||
inline friend bool operator<(const char *lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) < 0);
|
||||
}
|
||||
inline friend bool operator>(rcSTR_String lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) > 0);
|
||||
}
|
||||
inline friend bool operator>(rcSTR_String lhs, const char *rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) > 0);
|
||||
}
|
||||
inline friend bool operator>(const char *lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) > 0);
|
||||
}
|
||||
inline friend bool operator<=(rcSTR_String lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) <= 0);
|
||||
}
|
||||
inline friend bool operator<=(rcSTR_String lhs, const char *rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) <= 0);
|
||||
}
|
||||
inline friend bool operator<=(const char *lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) <= 0);
|
||||
}
|
||||
inline friend bool operator>=(rcSTR_String lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) >= 0);
|
||||
}
|
||||
inline friend bool operator>=(rcSTR_String lhs, const char *rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) >= 0);
|
||||
}
|
||||
inline friend bool operator>=(const char *lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strcmp(lhs, rhs) >= 0);
|
||||
}
|
||||
inline friend bool operator==(rcSTR_String lhs, rcSTR_String rhs)
|
||||
{
|
||||
return ((lhs.Length() == rhs.Length()) && (memcmp(lhs, rhs, lhs.Length()) == 0));
|
||||
}
|
||||
inline friend bool operator==(rcSTR_String lhs, const char *rhs)
|
||||
{
|
||||
return (strncmp(lhs, rhs, lhs.Length() + 1) == 0);
|
||||
}
|
||||
inline friend bool operator==(const char *lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strncmp(lhs, rhs, rhs.Length() + 1) == 0);
|
||||
}
|
||||
inline friend bool operator!=(rcSTR_String lhs, rcSTR_String rhs)
|
||||
{
|
||||
return ((lhs.Length() != rhs.Length()) || (memcmp(lhs, rhs, lhs.Length()) != 0));
|
||||
}
|
||||
inline friend bool operator!=(rcSTR_String lhs, const char *rhs)
|
||||
{
|
||||
return (strncmp(lhs, rhs, lhs.Length() + 1) != 0);
|
||||
}
|
||||
inline friend bool operator!=(const char *lhs, rcSTR_String rhs)
|
||||
{
|
||||
return (strncmp(lhs, rhs, rhs.Length() + 1) != 0);
|
||||
}
|
||||
|
||||
// serializing
|
||||
// int Serialize(pCStream stream);
|
||||
|
||||
protected:
|
||||
// Implementation
|
||||
void AllocBuffer(int len, bool keep_contents);
|
||||
rcSTR_String Copy(const char *src, int len);
|
||||
rcSTR_String Concat(const char *data, int len);
|
||||
|
||||
static bool isLower(char c)
|
||||
{
|
||||
return !isUpper(c);
|
||||
}
|
||||
static bool isUpper(char c)
|
||||
{
|
||||
return (c >= 'A') && (c <= 'Z');
|
||||
}
|
||||
static bool isSpace(char c)
|
||||
{
|
||||
return (c == ' ') || (c == '\t');
|
||||
}
|
||||
|
||||
char *m_data; // -> STR_String data
|
||||
int m_len; // z Data length
|
||||
int m_max; // Space in data buffer
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("CXX:STR_String")
|
||||
#endif
|
||||
};
|
||||
|
||||
inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs)
|
||||
{
|
||||
return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length());
|
||||
}
|
||||
inline STR_String operator+(rcSTR_String lhs, char rhs)
|
||||
{
|
||||
return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1);
|
||||
}
|
||||
inline STR_String operator+(char lhs, rcSTR_String rhs)
|
||||
{
|
||||
return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length());
|
||||
}
|
||||
inline STR_String operator+(rcSTR_String lhs, const char *rhs)
|
||||
{
|
||||
return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs));
|
||||
}
|
||||
inline STR_String operator+(const char *lhs, rcSTR_String rhs)
|
||||
{
|
||||
return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length());
|
||||
}
|
||||
|
||||
#endif //__STR_STRING_H__
|
@@ -1,637 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup string
|
||||
*
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* This file was formerly known as: GEN_StdString.cpp.
|
||||
*/
|
||||
|
||||
#include "STR_String.h"
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------
|
||||
Construction / destruction
|
||||
-------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#define STR_STRING_SIZE_DEFAULT_WORD 32 /* default size for a new word */
|
||||
#define STR_STRING_SIZE_DEFAULT_CHAR 9 /* default size for a new char */
|
||||
|
||||
//
|
||||
// Construct an empty string
|
||||
//
|
||||
STR_String::STR_String()
|
||||
: m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_len(0), m_max(STR_STRING_SIZE_DEFAULT_WORD)
|
||||
{
|
||||
this->m_data[0] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Construct a string of one character
|
||||
//
|
||||
STR_String::STR_String(char c)
|
||||
: m_data(new char[STR_STRING_SIZE_DEFAULT_CHAR]), m_len(1), m_max(STR_STRING_SIZE_DEFAULT_CHAR)
|
||||
{
|
||||
this->m_data[0] = c;
|
||||
this->m_data[1] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Construct a string of multiple repeating characters
|
||||
//
|
||||
STR_String::STR_String(char c, int len) : m_data(new char[len + 8]), m_len(len), m_max(len + 8)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
memset(this->m_data, c, len);
|
||||
this->m_data[len] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Construct a string from a pointer-to-ASCIIZ-string
|
||||
//
|
||||
// MAART: Changed to test for null strings
|
||||
STR_String::STR_String(const char *str)
|
||||
{
|
||||
if (str) {
|
||||
this->m_len = ::strlen(str);
|
||||
this->m_max = this->m_len + 8;
|
||||
this->m_data = new char[this->m_max];
|
||||
assertd(this->m_data != NULL);
|
||||
::memcpy(this->m_data, str, this->m_len);
|
||||
this->m_data[this->m_len] = 0;
|
||||
}
|
||||
else {
|
||||
this->m_data = NULL;
|
||||
this->m_len = 0;
|
||||
this->m_max = 8;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Construct a string from a pointer-to-ASCII-string and a length
|
||||
//
|
||||
STR_String::STR_String(const char *str, int len)
|
||||
: m_data(new char[len + 8]), m_len(len), m_max(len + 8)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
memcpy(this->m_data, str, len);
|
||||
this->m_data[len] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Construct a string from another string
|
||||
//
|
||||
STR_String::STR_String(rcSTR_String str)
|
||||
: m_data(new char[str.Length() + 8]), m_len(str.Length()), m_max(str.Length() + 8)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
assertd(str.this->m_data != NULL);
|
||||
memcpy(this->m_data, str.ReadPtr(), str.Length());
|
||||
this->m_data[str.Length()] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Construct a string from the first number of characters in another string
|
||||
//
|
||||
STR_String::STR_String(rcSTR_String str, int len)
|
||||
: m_data(new char[len + 8]), m_len(len), m_max(len + 8)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
assertd(str.this->m_data != NULL);
|
||||
memcpy(this->m_data, str.ReadPtr(), str.Length());
|
||||
this->m_data[str.Length()] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a string by concatenating two sources
|
||||
//
|
||||
STR_String::STR_String(const char *src1, int len1, const char *src2, int len2)
|
||||
: m_data(new char[len1 + len2 + 8]), m_len(len1 + len2), m_max(len1 + len2 + 8)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
memcpy(this->m_data, src1, len1);
|
||||
memcpy(this->m_data + len1, src2, len2);
|
||||
this->m_data[len1 + len2] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a string with an integer value
|
||||
//
|
||||
STR_String::STR_String(int val)
|
||||
: m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
this->m_len = sprintf(this->m_data, "%d", val);
|
||||
}
|
||||
|
||||
//
|
||||
// Create a string with a dword value
|
||||
//
|
||||
STR_String::STR_String(dword val)
|
||||
: m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
this->m_len = sprintf(this->m_data, "%lu", val);
|
||||
}
|
||||
|
||||
//
|
||||
// Create a string with a floating point value
|
||||
//
|
||||
STR_String::STR_String(float val)
|
||||
: m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
this->m_len = sprintf(this->m_data, "%g", val);
|
||||
}
|
||||
|
||||
//
|
||||
// Create a string with a double value
|
||||
//
|
||||
STR_String::STR_String(double val)
|
||||
: m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), m_max(STR_STRING_SIZE_DEFAULT_WORD)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
this->m_len = sprintf(this->m_data, "%g", val);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------
|
||||
Buffer management
|
||||
-------------------------------------------------------------------------------------------------*/
|
||||
|
||||
//
|
||||
// Make sure that the allocated buffer is at least <len> in size
|
||||
//
|
||||
void STR_String::AllocBuffer(int len, bool keep_contents)
|
||||
{
|
||||
// Check if we have enough space
|
||||
if (len + 1 <= this->m_max)
|
||||
return;
|
||||
|
||||
// Reallocate string
|
||||
char *new_data = new char[len + 8];
|
||||
if (keep_contents) {
|
||||
memcpy(new_data, this->m_data, this->m_len);
|
||||
}
|
||||
delete[] this->m_data;
|
||||
|
||||
// Accept new data
|
||||
this->m_max = len + 8;
|
||||
this->m_data = new_data;
|
||||
assertd(this->m_data != NULL);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------
|
||||
Basic string operations
|
||||
-------------------------------------------------------------------------------------------------*/
|
||||
|
||||
//
|
||||
// Format string (as does sprintf)
|
||||
//
|
||||
STR_String &STR_String::Format(const char *fmt, ...)
|
||||
{
|
||||
AllocBuffer(2048, false);
|
||||
|
||||
assertd(this->m_data != NULL);
|
||||
// Expand arguments and format to string
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
this->m_len = vsprintf(this->m_data, fmt, args);
|
||||
assertd(this->m_len <= 2048);
|
||||
va_end(args);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Format string (as does sprintf)
|
||||
//
|
||||
STR_String &STR_String::FormatAdd(const char *fmt, ...)
|
||||
{
|
||||
AllocBuffer(2048, false);
|
||||
|
||||
assertd(this->m_data != NULL);
|
||||
// Expand arguments and format to string
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
this->m_len += vsprintf(this->m_data + this->m_len, fmt, args);
|
||||
assertd(this->m_len <= 2048);
|
||||
va_end(args);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------
|
||||
Properties
|
||||
-------------------------------------------------------------------------------------------------*/
|
||||
|
||||
//
|
||||
// Check if string is entirely in UPPERCase
|
||||
//
|
||||
bool STR_String::IsUpper() const
|
||||
{
|
||||
for (int i = 0; i < this->m_len; i++)
|
||||
if (isLower(this->m_data[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if string is entirely in lowerCase
|
||||
//
|
||||
bool STR_String::IsLower() const
|
||||
{
|
||||
for (int i = 0; i < this->m_len; i++)
|
||||
if (isUpper(this->m_data[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------
|
||||
Search/Replace
|
||||
-------------------------------------------------------------------------------------------------*/
|
||||
|
||||
//
|
||||
// Find the first orccurence of <c> in the string
|
||||
//
|
||||
int STR_String::Find(char c, int pos) const
|
||||
{
|
||||
assertd(pos >= 0);
|
||||
assertd(this->m_len == 0 || pos < this->m_len);
|
||||
assertd(this->m_data != NULL);
|
||||
char *find_pos = strchr(this->m_data + pos, c);
|
||||
return (find_pos) ? (find_pos - this->m_data) : -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the first occurrence of <str> in the string
|
||||
//
|
||||
int STR_String::Find(const char *str, int pos) const
|
||||
{
|
||||
assertd(pos >= 0);
|
||||
assertd(this->m_len == 0 || pos < this->m_len);
|
||||
assertd(this->m_data != NULL);
|
||||
char *find_pos = strstr(this->m_data + pos, str);
|
||||
return (find_pos) ? (find_pos - this->m_data) : -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the first occurrence of <str> in the string
|
||||
//
|
||||
int STR_String::Find(rcSTR_String str, int pos) const
|
||||
{
|
||||
assertd(pos >= 0);
|
||||
assertd(this->m_len == 0 || pos < this->m_len);
|
||||
assertd(this->m_data != NULL);
|
||||
char *find_pos = strstr(this->m_data + pos, str.ReadPtr());
|
||||
return (find_pos) ? (find_pos - this->m_data) : -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the last occurrence of <c> in the string
|
||||
//
|
||||
int STR_String::RFind(char c) const
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
char *pos = strrchr(this->m_data, c);
|
||||
return (pos) ? (pos - this->m_data) : -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Find the first occurrence of any character in character set <set> in the string
|
||||
//
|
||||
int STR_String::FindOneOf(const char *set, int pos) const
|
||||
{
|
||||
assertd(pos >= 0);
|
||||
assertd(this->m_len == 0 || pos < this->m_len);
|
||||
assertd(this->m_data != NULL);
|
||||
char *find_pos = strpbrk(this->m_data + pos, set);
|
||||
return (find_pos) ? (find_pos - this->m_data) : -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Replace a character in this string with another string
|
||||
//
|
||||
void STR_String::Replace(int pos, rcSTR_String str)
|
||||
{
|
||||
// bounds(pos, 0, Length()-1);
|
||||
|
||||
if (str.Length() < 1) {
|
||||
// Remove one character from the string
|
||||
memcpy(this->m_data + pos, this->m_data + pos + 1, this->m_len - pos);
|
||||
}
|
||||
else {
|
||||
// Insert zero or more characters into the string
|
||||
AllocBuffer(this->m_len + str.Length() - 1, true);
|
||||
if (str.Length() != 1)
|
||||
memcpy(this->m_data + pos + str.Length(), this->m_data + pos + 1, Length() - pos);
|
||||
memcpy(this->m_data + pos, str.ReadPtr(), str.Length());
|
||||
}
|
||||
|
||||
this->m_len += str.Length() - 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Replace a substring of this string with another string
|
||||
//
|
||||
void STR_String::Replace(int pos, int num, rcSTR_String str)
|
||||
{
|
||||
// bounds(pos, 0, Length()-1);
|
||||
// bounds(pos+num, 0, Length());
|
||||
assertd(num >= 1);
|
||||
|
||||
if (str.Length() < num) {
|
||||
// Remove some data from the string by replacement
|
||||
memcpy(
|
||||
this->m_data + pos + str.Length(), this->m_data + pos + num, this->m_len - pos - num + 1);
|
||||
memcpy(this->m_data + pos, str.ReadPtr(), str.Length());
|
||||
}
|
||||
else {
|
||||
// Insert zero or more characters into the string
|
||||
AllocBuffer(this->m_len + str.Length() - num, true);
|
||||
if (str.Length() != num)
|
||||
memcpy(
|
||||
this->m_data + pos + str.Length(), this->m_data + pos + num, Length() - pos - num + 1);
|
||||
memcpy(this->m_data + pos, str.ReadPtr(), str.Length());
|
||||
}
|
||||
|
||||
this->m_len += str.Length() - num;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------
|
||||
Comparison
|
||||
-------------------------------------------------------------------------------------------------*/
|
||||
|
||||
//
|
||||
// Compare two strings and return the result,
|
||||
// <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
|
||||
//
|
||||
int STR_String::Compare(rcSTR_String rhs) const
|
||||
{
|
||||
return strcmp(this->ReadPtr(), rhs.ReadPtr());
|
||||
}
|
||||
|
||||
//
|
||||
// Compare two strings without respecting case and return the result,
|
||||
// <0 if *this<rhs, >0 if *this>rhs or 0 if *this==rhs
|
||||
//
|
||||
int STR_String::CompareNoCase(rcSTR_String rhs) const
|
||||
{
|
||||
#ifdef WIN32
|
||||
return stricmp(this->ReadPtr(), rhs.ReadPtr());
|
||||
#else
|
||||
return strcasecmp(this->ReadPtr(), rhs.ReadPtr());
|
||||
#endif
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------
|
||||
Formatting
|
||||
-------------------------------------------------------------------------------------------------*/
|
||||
|
||||
//
|
||||
// Capitalize string, "heLLo" -> "HELLO"
|
||||
//
|
||||
STR_String &STR_String::Upper()
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
#ifdef WIN32
|
||||
_strupr(this->m_data);
|
||||
#else
|
||||
for (int i = 0; i < this->m_len; i++)
|
||||
this->m_data[i] = (this->m_data[i] >= 'a' && this->m_data[i] <= 'z') ?
|
||||
this->m_data[i] + 'A' - 'a' :
|
||||
this->m_data[i];
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Lower string, "heLLo" -> "hello"
|
||||
//
|
||||
STR_String &STR_String::Lower()
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
#ifdef WIN32
|
||||
_strlwr(this->m_data);
|
||||
#else
|
||||
for (int i = 0; i < this->m_len; i++)
|
||||
this->m_data[i] = (this->m_data[i] >= 'A' && this->m_data[i] <= 'Z') ?
|
||||
this->m_data[i] + 'a' - 'A' :
|
||||
this->m_data[i];
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Capitalize string, "heLLo" -> "Hello"
|
||||
//
|
||||
STR_String &STR_String::Capitalize()
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
#ifdef WIN32
|
||||
if (this->m_len > 0)
|
||||
this->m_data[0] = toupper(this->m_data[0]);
|
||||
if (this->m_len > 1)
|
||||
_strlwr(this->m_data + 1);
|
||||
#else
|
||||
if (this->m_len > 0)
|
||||
this->m_data[0] = (this->m_data[0] >= 'a' && this->m_data[0] <= 'z') ?
|
||||
this->m_data[0] + 'A' - 'a' :
|
||||
this->m_data[0];
|
||||
for (int i = 1; i < this->m_len; i++)
|
||||
this->m_data[i] = (this->m_data[i] >= 'A' && this->m_data[i] <= 'Z') ?
|
||||
this->m_data[i] + 'a' - 'A' :
|
||||
this->m_data[i];
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim whitespace from the left side of the string
|
||||
//
|
||||
STR_String &STR_String::TrimLeft()
|
||||
{
|
||||
int skip;
|
||||
assertd(this->m_data != NULL);
|
||||
for (skip = 0; isSpace(this->m_data[skip]); skip++, this->m_len--) {
|
||||
/* pass */
|
||||
}
|
||||
memmove(this->m_data, this->m_data + skip, this->m_len + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim whitespaces from the right side of the string
|
||||
//
|
||||
STR_String &STR_String::TrimRight()
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
while (this->m_len && isSpace(this->m_data[this->m_len - 1]))
|
||||
this->m_len--;
|
||||
this->m_data[this->m_len] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim spaces from both sides of the character set
|
||||
//
|
||||
STR_String &STR_String::Trim()
|
||||
{
|
||||
TrimRight();
|
||||
TrimLeft();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim characters from the character set <set> from the left side of the string
|
||||
//
|
||||
STR_String &STR_String::TrimLeft(char *set)
|
||||
{
|
||||
int skip;
|
||||
assertd(this->m_data != NULL);
|
||||
for (skip = 0; this->m_len && strchr(set, this->m_data[skip]); skip++, this->m_len--) {
|
||||
/* pass */
|
||||
}
|
||||
memmove(this->m_data, this->m_data + skip, this->m_len + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim characters from the character set <set> from the right side of the string
|
||||
//
|
||||
STR_String &STR_String::TrimRight(char *set)
|
||||
{
|
||||
assertd(this->m_data != NULL);
|
||||
while (this->m_len && strchr(set, this->m_data[this->m_len - 1]))
|
||||
this->m_len--;
|
||||
this->m_data[this->m_len] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim characters from the character set <set> from both sides of the character set
|
||||
//
|
||||
STR_String &STR_String::Trim(char *set)
|
||||
{
|
||||
TrimRight(set);
|
||||
TrimLeft(set);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Trim quotes from both sides of the string
|
||||
//
|
||||
STR_String &STR_String::TrimQuotes()
|
||||
{
|
||||
// Trim quotes if they are on both sides of the string
|
||||
assertd(this->m_data != NULL);
|
||||
if ((this->m_len >= 2) && (this->m_data[0] == '\"') && (this->m_data[this->m_len - 1] == '\"')) {
|
||||
memmove(this->m_data, this->m_data + 1, this->m_len - 2 + 1);
|
||||
this->m_len -= 2;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------
|
||||
Assignment/Concatenation
|
||||
-------------------------------------------------------------------------------------------------*/
|
||||
|
||||
//
|
||||
// Set the string's conents to a copy of <src> with length <len>
|
||||
//
|
||||
rcSTR_String STR_String::Copy(const char *src, int len)
|
||||
{
|
||||
assertd(len >= 0);
|
||||
assertd(src);
|
||||
assertd(this->m_data != NULL);
|
||||
|
||||
AllocBuffer(len, false);
|
||||
this->m_len = len;
|
||||
memcpy(this->m_data, src, len);
|
||||
this->m_data[this->m_len] = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Concate a number of bytes to the current string
|
||||
//
|
||||
rcSTR_String STR_String::Concat(const char *data, int len)
|
||||
{
|
||||
assertd(this->m_len >= 0);
|
||||
assertd(len >= 0);
|
||||
assertd(data);
|
||||
assertd(this->m_data != NULL);
|
||||
|
||||
AllocBuffer(this->m_len + len, true);
|
||||
memcpy(this->m_data + this->m_len, data, len);
|
||||
this->m_len += len;
|
||||
this->m_data[this->m_len] = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<STR_String> STR_String::Explode(char c) const
|
||||
{
|
||||
STR_String lcv = *this;
|
||||
std::vector<STR_String> uc;
|
||||
|
||||
while (lcv.Length()) {
|
||||
int pos = lcv.Find(c);
|
||||
if (pos < 0) {
|
||||
uc.push_back(lcv);
|
||||
lcv.Clear();
|
||||
}
|
||||
else {
|
||||
uc.push_back(lcv.Left(pos));
|
||||
lcv = lcv.Mid(pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// uc. -= STR_String("");
|
||||
|
||||
return uc;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
int STR_String::Serialize(pCStream stream)
|
||||
{
|
||||
if (stream->GetAccess() == CStream::Access_Read) {
|
||||
int ln;
|
||||
stream->Read(&ln, sizeof(ln));
|
||||
AllocBuffer(ln, false);
|
||||
stream->Read(this->m_data, ln);
|
||||
this->m_data[ln] = '\0';
|
||||
this->m_len = ln;
|
||||
}
|
||||
else {
|
||||
stream->Write(&this->m_len, sizeof(this->m_len));
|
||||
stream->Write(this->m_data, this->m_len);
|
||||
}
|
||||
|
||||
return this->m_len + sizeof(this->m_len);
|
||||
}
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user