Compare commits
858 Commits
temp-ui-tw
...
temp_test_
Author | SHA1 | Date | |
---|---|---|---|
c8004ff653 | |||
fdffbf87ac | |||
bee00909bc | |||
562723b080 | |||
2195a5eb2c | |||
4307c0eb68 | |||
2d473ff4a8 | |||
2b2b569229 | |||
015dae3dc5 | |||
3fc687ad75 | |||
76beed9068 | |||
645aee0835 | |||
83bfa950b1 | |||
898625547f | |||
73150981c8 | |||
c9f1e104da | |||
336b263b56 | |||
b3ed969b86 | |||
87feba04dd | |||
1ca57bc5f4 | |||
7749b89d74 | |||
bae92a0ce5 | |||
5223f73a1d | |||
fe47584316 | |||
2d3d6eb7b2 | |||
f0c35d16f3 | |||
85d274a60c | |||
d3bba94bf2 | |||
04c3690299 | |||
627edd1efa | |||
445889676b | |||
350e783668 | |||
0b2aee5841 | |||
ecdd6a302e | |||
173f5f94ff | |||
0eeaeb3fc2 | |||
3df335d330 | |||
0676928408 | |||
e68667a835 | |||
86972d294f | |||
f52a03dd71 | |||
a52f89a446 | |||
9f3bafc4ab | |||
bb1096f475 | |||
3e6edf5278 | |||
37bce7b701 | |||
6febbd7a55 | |||
416c7a32d8 | |||
d4badd4b22 | |||
4e43e09cca | |||
21b6d78cd2 | |||
2b20931707 | |||
416686707f | |||
8bfbbc467a | |||
baa24243a5 | |||
73529fb1bb | |||
381ef09073 | |||
56ba339cd8 | |||
055fa3fa5e | |||
7d5c3beb06 | |||
39b0e9df81 | |||
6648f82ef7 | |||
320ff87948 | |||
b21595cdf9 | |||
e4b36fb6bc | |||
966e4ba9ae | |||
268682527f | |||
cdb52aee9f | |||
8b02ab86f1 | |||
019700583b | |||
31d2b04411 | |||
3508c699fb | |||
8ea7c93a37 | |||
8b8733e76c | |||
4dda04eaa9 | |||
30691560fa | |||
12f87d02c6 | |||
9680edf77c | |||
a00bfa8976 | |||
bde54e127e | |||
9b8c82e2ed | |||
5866a4680d | |||
d795144f54 | |||
de6258c618 | |||
d912ceeb40 | |||
9a197a1185 | |||
36785c83f0 | |||
8eb7a04150 | |||
97c3e5944c | |||
6f523ffacb | |||
04562794df | |||
93004c7b19 | |||
0d542db1e1 | |||
de1f2c41fa | |||
106f542ac4 | |||
83f94ebb6f | |||
954aa88ba4 | |||
9503751c83 | |||
dcaba4c5e3 | |||
fb463a13cd | |||
b5100e73c8 | |||
ab632243e6 | |||
8510c77b9c | |||
40aa321dc7 | |||
a80c381ec5 | |||
1e9a7383ef | |||
dc738de90c | |||
8ed4c5fc61 | |||
76bd253be7 | |||
c78b0874ad | |||
b991a92aab | |||
01965a275c | |||
b2dc8bd92e | |||
d3faf09082 | |||
b243eb2646 | |||
fcfb47b983 | |||
c1f5ac7cfe | |||
89897140cf | |||
af71984942 | |||
ec4b9dff19 | |||
d71b6d37fe | |||
2689124320 | |||
70a4956020 | |||
93305b97df | |||
7cd74015f8 | |||
7bd521a5c4 | |||
7dda5ac5ba | |||
1694e2aca4 | |||
2fddbebf93 | |||
4247a56cde | |||
e3b58b6451 | |||
5b10d08db3 | |||
7c4eb4f8db | |||
792292e3de | |||
95a969e7d5 | |||
f9c0c9e70c | |||
![]() |
3600e9057b | ||
![]() |
a78ecfe0f3 | ||
![]() |
65127f9875 | ||
![]() |
37c2bbe5ea | ||
![]() |
ceac1d91e2 | ||
![]() |
dfab5a0c4a | ||
![]() |
85379482d5 | ||
4ca249018d | |||
d529e13d65 | |||
4e797dbc69 | |||
![]() |
41a8e94d4d | ||
1b9a835893 | |||
320a1b6f35 | |||
f07f56aa37 | |||
4e91e72d53 | |||
58b4688c34 | |||
2f862bc7b9 | |||
4674795591 | |||
be9017c349 | |||
4c2f5b80b7 | |||
0502b0103f | |||
e8b717ee42 | |||
4b4ac93acd | |||
![]() |
f283c527d2 | ||
![]() |
820d086719 | ||
![]() |
69668d62ba | ||
![]() |
351744f2b0 | ||
![]() |
5ac471a021 | ||
![]() |
db932ccde6 | ||
57286eed8d | |||
9dbf3b9fab | |||
4f8c63e77b | |||
47c226cbe3 | |||
d0759840a0 | |||
5b19b2cb56 | |||
dcb00bf529 | |||
e8e062f866 | |||
9838e9e485 | |||
d66d5b431e | |||
43a0fe378f | |||
199f846072 | |||
fb6636c812 | |||
adc8980dec | |||
48c41b189a | |||
7562ad5777 | |||
27986e9b56 | |||
dba4f30328 | |||
83c491f044 | |||
7ef7843ada | |||
5a7b9adef1 | |||
d293de425f | |||
17d4c7abb1 | |||
2f81449a70 | |||
ca4ac36c59 | |||
5c328ab8b0 | |||
7a67cb2aeb | |||
178c3a4064 | |||
15884510e8 | |||
22e2e4f062 | |||
3ccc160682 | |||
00fd823bcd | |||
d9badbf25c | |||
f16e35ce0a | |||
425e5c8d76 | |||
1ab412f13d | |||
ee1c0c682b | |||
59f0811ac9 | |||
45f522888b | |||
d15262ded1 | |||
ab5b138805 | |||
8ca52a7757 | |||
d4af8a8d26 | |||
b1e59f1a20 | |||
bd34d77a90 | |||
3ac83dcc73 | |||
900178d438 | |||
414b8b7628 | |||
4adc0a7798 | |||
88620e8cd9 | |||
552e44bd25 | |||
1f19a86150 | |||
702376e935 | |||
3ca3098ed7 | |||
995702da48 | |||
33066542ca | |||
5a26ea0961 | |||
1e3e79fe7b | |||
d4292bbd28 | |||
a97c5d7daa | |||
6b009b8890 | |||
3d16099a77 | |||
4352980b0f | |||
3d6ac0bd7b | |||
71959181ad | |||
daa4a33383 | |||
d3695eb12c | |||
c1f236dcd4 | |||
3276c3b4a1 | |||
a90533e9b8 | |||
9bea7259e1 | |||
7fca310f25 | |||
27f4f761e7 | |||
17fafe2f63 | |||
89d56ea225 | |||
cfd6d48aab | |||
6be2c079c1 | |||
ae5d971e8f | |||
13bdc4a7e6 | |||
72aad83780 | |||
32ceaa7919 | |||
ec4786d00b | |||
582c30d32f | |||
b047b333b0 | |||
f2c9706781 | |||
fa06238aa7 | |||
b8a8e4f9b1 | |||
dbe767f5d9 | |||
fad42fc6c7 | |||
7cf3b1f472 | |||
6c3b29a14c | |||
febfaecd97 | |||
2d98802905 | |||
f70a8c1581 | |||
8eeacca9cb | |||
82847af9f9 | |||
ee19a80041 | |||
013eee7ec6 | |||
ce0b4e6681 | |||
d1cf59e547 | |||
d0407b0ed5 | |||
83a855a8a1 | |||
9e46eebcf1 | |||
786781304c | |||
2e888bfe6c | |||
901d6e68d7 | |||
3028d53865 | |||
fb5f6e762e | |||
02b4df9827 | |||
815d77192f | |||
9fab16f0f3 | |||
82f5e0200c | |||
032a35fb50 | |||
8a700673db | |||
0386350de6 | |||
d912d4735a | |||
97fc606c65 | |||
14be52f0fc | |||
739bb8f1d2 | |||
7107753f73 | |||
73c590e1eb | |||
44fd07c1c8 | |||
931a8da26c | |||
895fef5ccb | |||
b82a2fd9ab | |||
18a86af416 | |||
a0b5fd9cb6 | |||
553e8ffd1a | |||
fdc6fb2c53 | |||
8bc9286c4c | |||
4f8693652b | |||
d29378c2f2 | |||
0e6c07c063 | |||
cb3e0ff344 | |||
11d1fdeb34 | |||
430641d481 | |||
4745f29971 | |||
8512b1b5dd | |||
674bc2e4b4 | |||
b240973412 | |||
39994c3208 | |||
8189f2c806 | |||
237ac342c9 | |||
465e804193 | |||
4ab8614cd1 | |||
dabff9af7d | |||
384a0930d1 | |||
a5fa9ec310 | |||
ed15d0c1b9 | |||
e07a95b86d | |||
b52e04f794 | |||
e74c298cf9 | |||
cd485a7c6f | |||
06341c19c4 | |||
a527bd5f48 | |||
7f14d519c0 | |||
64337d087d | |||
e1fae3cbee | |||
7dbb4c9b2d | |||
fe67ca56d6 | |||
68e4e1bb41 | |||
881df30a46 | |||
6f91eaad39 | |||
55045ed85a | |||
2582090824 | |||
55415cd62a | |||
d29bdda34c | |||
e3ee04dec5 | |||
347c8255ed | |||
8aac19cab5 | |||
b4536d274c | |||
d3ffaa8e52 | |||
f5588dfb70 | |||
4b308888d8 | |||
fdfa2045ec | |||
33af94dc46 | |||
8ea624aeaf | |||
e29cd298fe | |||
7bba304c57 | |||
0dc09668ce | |||
cfa6753518 | |||
2cf8c35578 | |||
aa116ba5ba | |||
d2c1357fc5 | |||
0bf2a1f8fe | |||
7be027075f | |||
215c346017 | |||
7c9235d0e0 | |||
e254cc23b2 | |||
f5a122309d | |||
dee286fc7e | |||
ab9b89ac5d | |||
ce9e0b53b1 | |||
ce6d9112aa | |||
20f4fe138e | |||
ecbf642ddd | |||
caf5f5767f | |||
e0cc387124 | |||
ebeb144701 | |||
924b13b03a | |||
75a1116b51 | |||
73a4b885ec | |||
f6cda6bf88 | |||
9ce0a2815d | |||
7d7dcce859 | |||
f429a7dc13 | |||
257562ad6d | |||
8883c76b9a | |||
dd77b22626 | |||
3d70805a68 | |||
b6f0176c10 | |||
6835ea72f2 | |||
6408c4ebf6 | |||
e557e4d03c | |||
02d482e8f2 | |||
525badbd7d | |||
49fa3dd5ff | |||
8b0bc7e3e8 | |||
ef4abf1212 | |||
6ce37c59ec | |||
6824d73b75 | |||
06762eefcf | |||
f791fc031e | |||
57b7eba4b6 | |||
abda36c076 | |||
476b333a3e | |||
4ad1a7ab31 | |||
5f5aa43ab1 | |||
4293db60b3 | |||
647c065b9c | |||
497e532e23 | |||
e1f338b9f4 | |||
15ef2d42f3 | |||
a9083cc0ee | |||
c8a03bc716 | |||
3efb094fd3 | |||
251440f538 | |||
cb0f159155 | |||
409a525fa9 | |||
966af5a075 | |||
5234e23c2c | |||
11613f8c7a | |||
8a98189bfb | |||
3678b87272 | |||
1f2b48eb45 | |||
dd1c4c84c9 | |||
de2625518b | |||
75709e4d57 | |||
6a74211f99 | |||
d3742022c2 | |||
75794afdcd | |||
b1b49f6130 | |||
ca60d520d9 | |||
2fd22fd663 | |||
04c85de559 | |||
407dd37573 | |||
0acaa40c08 | |||
f2024f7d99 | |||
a7b5bbf13f | |||
e696280b88 | |||
5e9eb1930f | |||
9a7cbff535 | |||
8dec2ca7ba | |||
098d0d782a | |||
779a268c6e | |||
13b7b69e7f | |||
148b39caec | |||
e9f9217f75 | |||
dd45a4bc6e | |||
1ccd92d0bb | |||
9f78a24eca | |||
930a9edc1e | |||
5cfe7bf72c | |||
422b1c64cd | |||
1edad56ffc | |||
ef3d68f17b | |||
094ffcf669 | |||
56d33186a4 | |||
d570feeffc | |||
158397a007 | |||
4e8c430c6e | |||
d8a4ebb068 | |||
6d46a3ca4e | |||
1751b3c7c1 | |||
8ae0573c0f | |||
be0194ef3e | |||
0a2ca5860f | |||
151cf0b9d9 | |||
12cb22d5f6 | |||
5c2bb6f93a | |||
2e99348da7 | |||
817ccc3a99 | |||
a429f73d2b | |||
5898cc25c9 | |||
c05c2c3fb7 | |||
f55c39a974 | |||
ebf94179b5 | |||
9e5a219f3f | |||
76de0eeb95 | |||
773c5c7464 | |||
7abdfb5c2a | |||
ad743c056f | |||
05bb102a30 | |||
b37fd7a14b | |||
4154943eef | |||
5d7f7b7065 | |||
09e394583e | |||
7baa3c7df3 | |||
06a8b84792 | |||
343950f0c0 | |||
da0ef1daac | |||
2eb35c7cc0 | |||
13952ecec1 | |||
214e802f5f | |||
697e6e53b8 | |||
64c0f1fc3f | |||
ca5ccb52e5 | |||
51e90a0ada | |||
822bbb19f1 | |||
a35da15228 | |||
53874b413e | |||
1b029b790b | |||
acd99f12e7 | |||
1a11ac5e34 | |||
416afcb1c3 | |||
3539cbc497 | |||
4288b2a1d1 | |||
d4548fe55b | |||
7b360abb18 | |||
b30294ba41 | |||
50f1bd6f09 | |||
![]() |
83d530688b | ||
b790b57fe1 | |||
14fe422b48 | |||
0af8ddab2d | |||
![]() |
79ecc59f0b | ||
![]() |
0ac4824d07 | ||
5f8d444a76 | |||
![]() |
42c5fdeff4 | ||
![]() |
54801f695c | ||
39ac38c25f | |||
834d3e15ce | |||
b3c00f97be | |||
6324e9bae8 | |||
bbdfd0cabe | |||
6ef557fdf1 | |||
30897a56e7 | |||
eb18eb709d | |||
fc7c57f4a1 | |||
e3fdfcc981 | |||
e9b6848fe7 | |||
38e61c04ea | |||
5e56eb8ca2 | |||
ccfc8aacf8 | |||
edece9e741 | |||
6ee1db0d67 | |||
30434e3904 | |||
e45986291d | |||
eb6e96006e | |||
9047bf89fa | |||
63ef98d056 | |||
bf53622eef | |||
f419d4625a | |||
ae19d5303a | |||
35f883b886 | |||
7d52658d84 | |||
974b50d16b | |||
55382bcdd9 | |||
51c931ebb5 | |||
0b9aaaf97f | |||
faccaee6c3 | |||
a56fb568ed | |||
c365e0c6b6 | |||
0d6deb7e65 | |||
50eed6e54f | |||
147cddb398 | |||
88c4684466 | |||
77a30a2886 | |||
370e2b5d82 | |||
44dc741e89 | |||
7a8cf94170 | |||
fd28c19d09 | |||
2f5eabf859 | |||
1a17c578a8 | |||
56e1ae1afa | |||
eea78bd112 | |||
d927f54da6 | |||
![]() |
ec8d1b4eae | ||
4e4c1f40e0 | |||
35ac8cf4dc | |||
2f2f14ffed | |||
03778b787e | |||
f7e062ef3e | |||
23cf808585 | |||
8e8845786f | |||
3ed1a99dd2 | |||
0a9bc6944c | |||
ec4e2f32c8 | |||
2ea03ff860 | |||
9a3f32f80f | |||
bcf2f30878 | |||
23312a6994 | |||
cf5a96aa8d | |||
7ed64d9430 | |||
1cc0f8cf75 | |||
b4e90b6e61 | |||
112c67f688 | |||
19fa6fd9f4 | |||
88921150ff | |||
e973c94036 | |||
b40f1f4c79 | |||
c191344efb | |||
debf4fc7c9 | |||
a60aca00bb | |||
763f96526e | |||
abfd14817f | |||
529cffd804 | |||
09bb5e3aa0 | |||
5fb15545c1 | |||
a2df63e996 | |||
ccaba71fdf | |||
710c72807f | |||
e779eab729 | |||
a72cf784a7 | |||
78dffe2f16 | |||
9d31943d88 | |||
0a2b19e96d | |||
46582b3743 | |||
c10b19e453 | |||
5631bd4f94 | |||
30b6d7826d | |||
d1b2c55322 | |||
87ae49c78e | |||
2765fb6c76 | |||
65cea9523e | |||
3d311fdaf1 | |||
7a0d5e0c9e | |||
e2fb2315fd | |||
fc1fc95b79 | |||
05703d630e | |||
65c358851d | |||
b997fc5ea1 | |||
869747e527 | |||
df7857a364 | |||
cd0cf0a5b7 | |||
abf7518cbf | |||
58406eddb5 | |||
97ab225428 | |||
24bbe05913 | |||
81ac9f61b6 | |||
a9f6ab7357 | |||
df9a5825e1 | |||
0c8b9cd7d1 | |||
142aba9485 | |||
bf632990e0 | |||
3b4a9b2319 | |||
38dce1d29d | |||
deeb0b3aac | |||
237b1f9d75 | |||
11cd86a8d2 | |||
27713d65d1 | |||
d37d96437e | |||
940fb3c044 | |||
f91a2a0831 | |||
6d6ab057e4 | |||
ea12ba5441 | |||
601d896fc6 | |||
c237a48104 | |||
29078186f8 | |||
7754c4f10f | |||
90931d6de9 | |||
4785f80d51 | |||
5136cc701f | |||
ef9eb626a8 | |||
0663576d19 | |||
e1b8577e41 | |||
e09d9c86b6 | |||
52e99c5639 | |||
193806f590 | |||
a3e4f9d9a6 | |||
482f46a35a | |||
975a17c816 | |||
985c6464e2 | |||
bca07d9039 | |||
35092510ba | |||
85842851d5 | |||
61ec4159c8 | |||
c4ebefc1c8 | |||
eb4f2f1548 | |||
47b4b45011 | |||
7547e28ba4 | |||
0b2e4fa52e | |||
f4900b3d02 | |||
1d53fbfd06 | |||
c203de25db | |||
ac8c589b7c | |||
f32d3f7b06 | |||
5385455e6a | |||
1bf726f1ad | |||
f031000b28 | |||
2c54c641a3 | |||
554be8d96c | |||
f969b3d440 | |||
6034a5bd5b | |||
eea756e513 | |||
ecbf3e2d0f | |||
6fa6a8851f | |||
b3fff9b07a | |||
671ef8f0e9 | |||
373b9b4481 | |||
0ada9c1638 | |||
31158ef0c9 | |||
5fbd436bb1 | |||
c0cb475689 | |||
b8a0455983 | |||
6145a6bc6c | |||
5c03d0c30c | |||
6b42781319 | |||
6c4a9b83ff | |||
9453b45e20 | |||
c0f19d6082 | |||
06078a6f92 | |||
1199b9e678 | |||
92bc9477d1 | |||
7bc1657d05 | |||
e582a4dc77 | |||
243e329ec3 | |||
5775efba2f | |||
cab8626cf2 | |||
19cb01aa21 | |||
6e6828e09d | |||
72ff64590d | |||
553724529e | |||
681e2b6134 | |||
49bd2228cb | |||
0a140ec66e | |||
f30225725d | |||
a1ac104f02 | |||
d823f6e2cf | |||
3042f6e608 | |||
6115091103 | |||
78ef2d0d84 | |||
9d92a97562 | |||
192670e8ce | |||
7ae1cc23fc | |||
ebb6648bda | |||
384f2956e5 | |||
2ba90cf717 | |||
e5af8597e5 | |||
1f6a7785f6 | |||
0ee053fb12 | |||
8cd4776764 | |||
f32bde6bd9 | |||
![]() |
8b808cefae | ||
f8466b6284 | |||
4a2d7a2f89 | |||
67defe866b | |||
b6575fed92 | |||
d6735bfae0 | |||
e4c45d0c5e | |||
c4668b750c | |||
81a85233a7 | |||
89f62e5dc3 | |||
408e13783d | |||
3900734063 | |||
fa688ac593 | |||
787f952ef4 | |||
63241d25b9 | |||
![]() |
98166b5c98 | ||
229849af0f | |||
0a1fc855bc | |||
46ccaff9a3 | |||
9c8b0a20c1 | |||
a42cf75ecb | |||
d77e884bd7 | |||
e2111233f0 | |||
e4efd04063 | |||
8edd20274e | |||
9be60839cd | |||
af934d751d | |||
5ac07c31f0 | |||
f3a7d9375d | |||
a033a0eaaf | |||
c137b53569 | |||
f0a9986ccf | |||
f639ffe795 | |||
326381bfe1 | |||
174e3c6b65 | |||
5c899dcc92 | |||
24ee80f077 | |||
22b69af796 | |||
0758c006ec | |||
c2a329ec07 | |||
bdaee543f3 | |||
44d358c384 | |||
f87123a6eb | |||
f2fc2cd521 | |||
af92a39e37 | |||
49cbb23855 | |||
9cb84de509 | |||
53f6991de8 | |||
5b696c2bd8 | |||
b95a5c2e68 | |||
080e78d205 | |||
a55a69f81a | |||
596fea8afd | |||
47e4adde5a | |||
a349943cd7 | |||
360faf5c3c | |||
9cf97857d1 | |||
44bdf515ba | |||
45ccdebad3 | |||
d242d33571 | |||
731eaa68d3 | |||
344963bf23 | |||
aaca5731fb | |||
aa7147f665 | |||
0fb50afdc5 | |||
f3cc74d216 | |||
0946a8da3b | |||
a8e5e63f45 | |||
e52f8ac7ce | |||
71a088582a | |||
3aab8dd731 | |||
56d57b2e9d | |||
b16eb9d7ad | |||
3fcd3d41c4 | |||
0b0bfa0628 | |||
ff9ce5fd98 | |||
2d99e118b4 | |||
a93add61b0 | |||
7f28a99dd5 | |||
9aaf9857a0 | |||
e2595de761 | |||
40c4942901 | |||
2e188dc504 | |||
![]() |
dfce29b809 | ||
decf7adcf6 | |||
81531d5e76 | |||
15bc0b7d5d | |||
17dec471c5 | |||
81f05aca29 | |||
d1270925a5 | |||
9e09ae7aff | |||
![]() |
c51a5e1066 | ||
758452ffba | |||
c7cd82c356 | |||
cc554eea75 | |||
0d770432d6 | |||
b2cb9d4b1b | |||
08e19c6bc0 | |||
b928f58849 | |||
228c1e5345 | |||
488af21ae0 | |||
b54d7bfad8 | |||
2babf80ae6 | |||
022dcb8e6c | |||
6d66e81667 | |||
91a5e1aef8 | |||
6d704d57ad | |||
a1b1c840a0 | |||
901654dcbf | |||
37a657a45f | |||
e07bb3955e | |||
7834b59598 | |||
0c8d40d2de | |||
1014b6f455 | |||
093e29f3c2 | |||
0f0d1f8e2a | |||
43ccbe353f | |||
2d861122e1 | |||
66f8852e30 | |||
54ddb01299 | |||
3d47323162 | |||
5c77439264 | |||
e2c92c1341 | |||
faf8402c19 | |||
4c0bcc3d13 | |||
4fc4a7e1f4 | |||
f9859a3b2a | |||
6da9fa1bf2 | |||
5c6407c268 | |||
3214b1114f | |||
bfbe9a0d55 | |||
f482afadab | |||
661dcd813c | |||
5541de9a3a | |||
3791afa29c | |||
3ae8229843 | |||
f61d4b2e3a | |||
49f57d8de8 | |||
64c7bad391 | |||
4659855b0f |
@@ -263,6 +263,7 @@ ForEachMacros:
|
||||
- SET_SLOT_PROBING_BEGIN
|
||||
- MAP_SLOT_PROBING_BEGIN
|
||||
- VECTOR_SET_SLOT_PROBING_BEGIN
|
||||
- TGSET_ITER
|
||||
|
||||
StatementMacros:
|
||||
- PyObject_HEAD
|
||||
|
@@ -578,6 +578,12 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
|
||||
)
|
||||
find_library(
|
||||
COMPILER_ASAN_LIBRARY_THUNK NAMES clang_rt.asan_dll_thunk-x86_64
|
||||
PATHS
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
|
||||
)
|
||||
elseif(APPLE)
|
||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER}
|
||||
-print-file-name=lib
|
||||
@@ -598,6 +604,7 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(COMPILER_ASAN_LIBRARY_THUNK)
|
||||
mark_as_advanced(COMPILER_ASAN_LIBRARY)
|
||||
endif()
|
||||
endif()
|
||||
@@ -918,9 +925,9 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Release")
|
||||
unset(_list_COMPILER_ASAN_CFLAGS)
|
||||
unset(_is_CONFIG_DEBUG)
|
||||
elseif(COMPILER_ASAN_LIBRARY)
|
||||
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};${COMPILER_ASAN_LIBRARY}")
|
||||
set(PLATFORM_LINKFLAGS "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
|
||||
set(PLATFORM_LINKFLAGS_DEBUG "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
|
||||
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};\"${COMPILER_ASAN_LIBRARY}\" \"${COMPILER_ASAN_LIBRARY_THUNK}\"")
|
||||
set(PLATFORM_LINKFLAGS "\"${COMPILER_ASAN_LIBRARY}\" \"${COMPILER_ASAN_LIBRARY_THUNK}\" ${COMPILER_ASAN_LINKER_FLAGS}")
|
||||
set(PLATFORM_LINKFLAGS_DEBUG "\"${COMPILER_ASAN_LIBRARY}\" \"${COMPILER_ASAN_LIBRARY_THUNK}\" ${COMPILER_ASAN_LINKER_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
2
extern/Eigen3/Eigen/src/Core/util/Macros.h
vendored
2
extern/Eigen3/Eigen/src/Core/util/Macros.h
vendored
@@ -389,7 +389,7 @@
|
||||
|
||||
// Does the compiler support result_of?
|
||||
#ifndef EIGEN_HAS_STD_RESULT_OF
|
||||
#if EIGEN_MAX_CPP_VER>=11 && ((__has_feature(cxx_lambdas) || (defined(__cplusplus) && __cplusplus >= 201103L)))
|
||||
#if __cplusplus < 201703L && EIGEN_MAX_CPP_VER>=11 && ((__has_feature(cxx_lambdas) || (defined(__cplusplus) && __cplusplus >= 201103L && __cplusplus)))
|
||||
#define EIGEN_HAS_STD_RESULT_OF 1
|
||||
#else
|
||||
#define EIGEN_HAS_STD_RESULT_OF 0
|
||||
|
2
extern/audaspace/bindings/C/AUD_Device.cpp
vendored
2
extern/audaspace/bindings/C/AUD_Device.cpp
vendored
@@ -221,7 +221,7 @@ AUD_API void AUD_Device_setListenerVelocity(AUD_Device* device, const float valu
|
||||
AUD_API double AUD_Device_getRate(AUD_Device* device)
|
||||
{
|
||||
auto dev = device ? *device : DeviceManager::getDevice();
|
||||
return dev->getSpecs().rate;
|
||||
return dev ? dev->getSpecs().rate : 0.0;
|
||||
}
|
||||
|
||||
AUD_API float AUD_Device_getSpeedOfSound(AUD_Device* device)
|
||||
|
8
extern/audaspace/include/util/ThreadPool.h
vendored
8
extern/audaspace/include/util/ThreadPool.h
vendored
@@ -87,11 +87,17 @@ public:
|
||||
* \param args The arguments of the task.
|
||||
* \return A future of the same type as the return type of the task.
|
||||
*/
|
||||
#if __cplusplus > 201703L
|
||||
template<class T, class... Args>
|
||||
std::future<typename std::invoke_result<T, Args...>::type> enqueue(T&& t, Args&&... args)
|
||||
{
|
||||
using pkgdTask = std::packaged_task<typename std::invoke_result<T, Args...>::type()>;
|
||||
#else
|
||||
template<class T, class... Args>
|
||||
std::future<typename std::result_of<T(Args...)>::type> enqueue(T&& t, Args&&... args)
|
||||
{
|
||||
using pkgdTask = std::packaged_task<typename std::result_of<T(Args...)>::type()>;
|
||||
|
||||
#endif
|
||||
std::shared_ptr<pkgdTask> task = std::make_shared<pkgdTask>(std::bind(std::forward<T>(t), std::forward<Args>(args)...));
|
||||
auto result = task->get_future();
|
||||
|
||||
|
@@ -67,7 +67,7 @@ SET(LEMON_ENABLE_ILOG YES CACHE STRING "Enable ILOG (CPLEX) solver backend.")
|
||||
SET(LEMON_ENABLE_COIN YES CACHE STRING "Enable COIN solver backend.")
|
||||
SET(LEMON_ENABLE_SOPLEX YES CACHE STRING "Enable SoPlex solver backend.")
|
||||
|
||||
IF(LEMON_ENABLE_GLPK)
|
||||
IF(LEMON_ENABLE_GLPK)
|
||||
FIND_PACKAGE(GLPK 4.33)
|
||||
ENDIF(LEMON_ENABLE_GLPK)
|
||||
IF(LEMON_ENABLE_ILOG)
|
||||
|
@@ -4,7 +4,7 @@ FIND_PATH(ILOG_ROOT_DIR
|
||||
PATHS /opt/ibm/ILOG /usr/local/ibm/ILOG /usr/local/ILOG /usr/local/ilog
|
||||
PATHS "$ENV{HOME}/ILOG" "$ENV{HOME}/.local/ILOG"
|
||||
PATHS "$ENV{HOME}/ibm/ILOG" "$ENV{HOME}/.local/ibm/ILOG"
|
||||
PATHS "C:/Program Files/IBM/ILOG"
|
||||
PATHS "C:/Program Files/IBM/ILOG"
|
||||
PATH_SUFFIXES "CPLEX_Studio126" "CPLEX_Studio125"
|
||||
"CPLEX_Studio124" "CPLEX_Studio123" "CPLEX_Studio122"
|
||||
NO_DEFAULT_PATH
|
||||
|
@@ -16,3 +16,4 @@ LINK_DIRECTORIES(
|
||||
|
||||
# ADD_EXECUTABLE(myprog myprog-main.cc)
|
||||
# TARGET_LINK_LIBRARIES(myprog lemon)
|
||||
|
||||
|
@@ -88,3 +88,4 @@ INSTALL(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
|
||||
DESTINATION lib/pkgconfig
|
||||
)
|
||||
|
||||
|
3
extern/quadriflow/src/loader.cpp
vendored
3
extern/quadriflow/src/loader.cpp
vendored
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
|
||||
namespace qflow {
|
||||
|
||||
@@ -69,7 +70,7 @@ void load(const char* filename, MatrixXd& V, MatrixXi& F)
|
||||
};
|
||||
|
||||
/// Hash function for obj_vertex
|
||||
struct obj_vertexHash {
|
||||
struct obj_vertexHash : std::function<size_t(obj_vertex)> {
|
||||
std::size_t operator()(const obj_vertex &v) const {
|
||||
size_t hash = std::hash<uint32_t>()(v.p);
|
||||
hash = hash * 37 + std::hash<uint32_t>()(v.uv);
|
||||
|
BIN
icon_geom.blend
Normal file
BIN
icon_geom.blend
Normal file
Binary file not shown.
@@ -49,27 +49,27 @@
|
||||
/* Unsigned */
|
||||
ATOMIC_INLINE uint64_t atomic_add_and_fetch_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x) + x;
|
||||
return (uint64_t)(InterlockedExchangeAdd64((int64_t *)p, (int64_t)x) + (int64_t)x);
|
||||
}
|
||||
|
||||
ATOMIC_INLINE uint64_t atomic_sub_and_fetch_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x)) - x;
|
||||
return (uint64_t)(InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x)) - (int64_t)x);
|
||||
}
|
||||
|
||||
ATOMIC_INLINE uint64_t atomic_cas_uint64(uint64_t *v, uint64_t old, uint64_t _new)
|
||||
{
|
||||
return InterlockedCompareExchange64((int64_t *)v, _new, old);
|
||||
return (uint64_t)(InterlockedCompareExchange64((int64_t *)v, _new, old));
|
||||
}
|
||||
|
||||
ATOMIC_INLINE uint64_t atomic_fetch_and_add_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
return InterlockedExchangeAdd64((int64_t *)p, (int64_t)x);
|
||||
return (uint64_t)InterlockedExchangeAdd64((int64_t *)p, (int64_t)x);
|
||||
}
|
||||
|
||||
ATOMIC_INLINE uint64_t atomic_fetch_and_sub_uint64(uint64_t *p, uint64_t x)
|
||||
{
|
||||
return InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x));
|
||||
return (uint64_t)InterlockedExchangeAdd64((int64_t *)p, -((int64_t)x));
|
||||
}
|
||||
|
||||
/* Signed */
|
||||
@@ -103,32 +103,32 @@ ATOMIC_INLINE int64_t atomic_fetch_and_sub_int64(int64_t *p, int64_t x)
|
||||
/* Unsigned */
|
||||
ATOMIC_INLINE uint32_t atomic_add_and_fetch_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
return InterlockedExchangeAdd(p, x) + x;
|
||||
return (uint32_t)InterlockedExchangeAdd(p, x) + x;
|
||||
}
|
||||
|
||||
ATOMIC_INLINE uint32_t atomic_sub_and_fetch_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
return InterlockedExchangeAdd(p, -((int32_t)x)) - x;
|
||||
return (uint32_t)InterlockedExchangeAdd(p, -((int32_t)x)) - x;
|
||||
}
|
||||
|
||||
ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new)
|
||||
{
|
||||
return InterlockedCompareExchange((long *)v, _new, old);
|
||||
return (uint32_t)InterlockedCompareExchange((long *)v, _new, old);
|
||||
}
|
||||
|
||||
ATOMIC_INLINE uint32_t atomic_fetch_and_add_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
return InterlockedExchangeAdd(p, x);
|
||||
return (uint32_t)InterlockedExchangeAdd(p, x);
|
||||
}
|
||||
|
||||
ATOMIC_INLINE uint32_t atomic_fetch_and_or_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
return InterlockedOr((long *)p, x);
|
||||
return (uint32_t)InterlockedOr((long *)p, x);
|
||||
}
|
||||
|
||||
ATOMIC_INLINE uint32_t atomic_fetch_and_and_uint32(uint32_t *p, uint32_t x)
|
||||
{
|
||||
return InterlockedAnd((long *)p, x);
|
||||
return (uint32_t)InterlockedAnd((long *)p, x);
|
||||
}
|
||||
|
||||
/* Signed */
|
||||
@@ -205,9 +205,9 @@ ATOMIC_INLINE uint8_t atomic_fetch_and_or_uint8(uint8_t *p, uint8_t b)
|
||||
ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b)
|
||||
{
|
||||
#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
|
||||
return InterlockedAnd8((char *)p, (char)b);
|
||||
return (int8_t)InterlockedAnd8((char *)p, (char)b);
|
||||
#else
|
||||
return _InterlockedAnd8((char *)p, (char)b);
|
||||
return (int8_t)_InterlockedAnd8((char *)p, (char)b);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -215,9 +215,9 @@ ATOMIC_INLINE int8_t atomic_fetch_and_and_int8(int8_t *p, int8_t b)
|
||||
ATOMIC_INLINE int8_t atomic_fetch_and_or_int8(int8_t *p, int8_t b)
|
||||
{
|
||||
#if (LG_SIZEOF_PTR == 8 || LG_SIZEOF_INT == 8)
|
||||
return InterlockedOr8((char *)p, (char)b);
|
||||
return (int8_t)InterlockedOr8((char *)p, (char)b);
|
||||
#else
|
||||
return _InterlockedOr8((char *)p, (char)b);
|
||||
return (int8_t)_InterlockedOr8((char *)p, (char)b);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
set(INC
|
||||
.
|
||||
../atomic
|
||||
../../source/blender/blenlib
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
@@ -409,7 +409,7 @@ static void print_memhead_backtrace(MemHead *memh)
|
||||
(void)memh; /* Ignored. */
|
||||
}
|
||||
# endif /* defined(__linux__) || defined(__APPLE__) */
|
||||
#endif /* DEBUG_BACKTRACE */
|
||||
#endif /* DEBUG_BACKTRACE */
|
||||
|
||||
static void make_memhead_header(MemHead *memh, size_t len, const char *str)
|
||||
{
|
||||
|
@@ -30,6 +30,7 @@
|
||||
|
||||
/* to ensure strict conversions */
|
||||
#include "../../source/blender/blenlib/BLI_strict_flags.h"
|
||||
#include "../../source/blender/blenlib/BLI_asan.h"
|
||||
|
||||
#include "atomic_ops.h"
|
||||
#include "mallocn_intern.h"
|
||||
@@ -59,6 +60,9 @@ enum {
|
||||
#define MEMHEAD_ALIGNED_FROM_PTR(ptr) (((MemHeadAligned *)ptr) - 1)
|
||||
#define MEMHEAD_IS_ALIGNED(memhead) ((memhead)->len & (size_t)MEMHEAD_ALIGN_FLAG)
|
||||
|
||||
#define MEM_POISON_MEMHEAD(vmemh) BLI_asan_poison(MEMHEAD_FROM_PTR(vmemh), sizeof(MemHead))
|
||||
#define MEM_UNPOISON_MEMHEAD(vmemh) BLI_asan_unpoison(MEMHEAD_FROM_PTR(vmemh), sizeof(MemHead))
|
||||
|
||||
/* Uncomment this to have proper peak counter. */
|
||||
#define USE_ATOMIC_MAX
|
||||
|
||||
@@ -93,7 +97,13 @@ print_error(const char *str, ...)
|
||||
size_t MEM_lockfree_allocN_len(const void *vmemh)
|
||||
{
|
||||
if (vmemh) {
|
||||
return MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t)(MEMHEAD_ALIGN_FLAG));
|
||||
size_t ret;
|
||||
|
||||
MEM_UNPOISON_MEMHEAD(vmemh);
|
||||
ret = MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t)(MEMHEAD_ALIGN_FLAG));
|
||||
MEM_POISON_MEMHEAD(vmemh);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -119,6 +129,8 @@ void MEM_lockfree_freeN(void *vmemh)
|
||||
atomic_sub_and_fetch_u(&totblock, 1);
|
||||
atomic_sub_and_fetch_z(&mem_in_use, len);
|
||||
|
||||
MEM_UNPOISON_MEMHEAD(vmemh);
|
||||
|
||||
if (UNLIKELY(malloc_debug_memset && len)) {
|
||||
memset(memh + 1, 255, len);
|
||||
}
|
||||
@@ -137,6 +149,9 @@ void *MEM_lockfree_dupallocN(const void *vmemh)
|
||||
if (vmemh) {
|
||||
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
const size_t prev_size = MEM_lockfree_allocN_len(vmemh);
|
||||
|
||||
MEM_UNPOISON_MEMHEAD(vmemh);
|
||||
|
||||
if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
|
||||
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
newp = MEM_lockfree_mallocN_aligned(
|
||||
@@ -145,6 +160,8 @@ void *MEM_lockfree_dupallocN(const void *vmemh)
|
||||
else {
|
||||
newp = MEM_lockfree_mallocN(prev_size, "dupli_malloc");
|
||||
}
|
||||
|
||||
MEM_POISON_MEMHEAD(vmemh);
|
||||
memcpy(newp, vmemh, prev_size);
|
||||
}
|
||||
return newp;
|
||||
@@ -158,6 +175,8 @@ void *MEM_lockfree_reallocN_id(void *vmemh, size_t len, const char *str)
|
||||
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
size_t old_len = MEM_lockfree_allocN_len(vmemh);
|
||||
|
||||
MEM_UNPOISON_MEMHEAD(vmemh);
|
||||
|
||||
if (LIKELY(!MEMHEAD_IS_ALIGNED(memh))) {
|
||||
newp = MEM_lockfree_mallocN(len, "realloc");
|
||||
}
|
||||
@@ -166,6 +185,8 @@ void *MEM_lockfree_reallocN_id(void *vmemh, size_t len, const char *str)
|
||||
newp = MEM_lockfree_mallocN_aligned(len, (size_t)memh_aligned->alignment, "realloc");
|
||||
}
|
||||
|
||||
MEM_POISON_MEMHEAD(vmemh);
|
||||
|
||||
if (newp) {
|
||||
if (len < old_len) {
|
||||
/* shrink */
|
||||
@@ -194,6 +215,8 @@ void *MEM_lockfree_recallocN_id(void *vmemh, size_t len, const char *str)
|
||||
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
size_t old_len = MEM_lockfree_allocN_len(vmemh);
|
||||
|
||||
MEM_UNPOISON_MEMHEAD(vmemh);
|
||||
|
||||
if (LIKELY(!MEMHEAD_IS_ALIGNED(memh))) {
|
||||
newp = MEM_lockfree_mallocN(len, "recalloc");
|
||||
}
|
||||
@@ -201,6 +224,7 @@ void *MEM_lockfree_recallocN_id(void *vmemh, size_t len, const char *str)
|
||||
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
newp = MEM_lockfree_mallocN_aligned(len, (size_t)memh_aligned->alignment, "recalloc");
|
||||
}
|
||||
MEM_POISON_MEMHEAD(vmemh);
|
||||
|
||||
if (newp) {
|
||||
if (len < old_len) {
|
||||
@@ -241,6 +265,7 @@ void *MEM_lockfree_callocN(size_t len, const char *str)
|
||||
atomic_add_and_fetch_z(&mem_in_use, len);
|
||||
update_maximum(&peak_mem, mem_in_use);
|
||||
|
||||
MEM_POISON_MEMHEAD(PTR_FROM_MEMHEAD(memh));
|
||||
return PTR_FROM_MEMHEAD(memh);
|
||||
}
|
||||
print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
|
||||
@@ -286,6 +311,8 @@ void *MEM_lockfree_mallocN(size_t len, const char *str)
|
||||
atomic_add_and_fetch_z(&mem_in_use, len);
|
||||
update_maximum(&peak_mem, mem_in_use);
|
||||
|
||||
MEM_POISON_MEMHEAD(PTR_FROM_MEMHEAD(memh));
|
||||
|
||||
return PTR_FROM_MEMHEAD(memh);
|
||||
}
|
||||
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
|
||||
@@ -357,6 +384,8 @@ void *MEM_lockfree_mallocN_aligned(size_t len, size_t alignment, const char *str
|
||||
atomic_add_and_fetch_z(&mem_in_use, len);
|
||||
update_maximum(&peak_mem, mem_in_use);
|
||||
|
||||
MEM_POISON_MEMHEAD(PTR_FROM_MEMHEAD(memh));
|
||||
|
||||
return PTR_FROM_MEMHEAD(memh);
|
||||
}
|
||||
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
|
||||
|
@@ -70,9 +70,9 @@ static int check_if_canceled(float progress,
|
||||
return cancel;
|
||||
}
|
||||
|
||||
void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
|
||||
void (*update_cb)(void *, float progress, int *cancel),
|
||||
void *update_cb_data)
|
||||
ATTR_NO_OPT void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
|
||||
void (*update_cb)(void *, float progress, int *cancel),
|
||||
void *update_cb_data)
|
||||
{
|
||||
Parametrizer field;
|
||||
VertexMap vertexMap;
|
||||
@@ -80,6 +80,12 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
|
||||
/* Get remeshing parameters. */
|
||||
int faces = qrd->target_faces;
|
||||
|
||||
field.flag_adaptive_scale = 1;
|
||||
field.flag_minimum_cost_flow = 1;
|
||||
field.flag_preserve_boundary = 1;
|
||||
field.flag_preserve_sharp = 1;
|
||||
// field.flag_aggresive_sat = 1;
|
||||
|
||||
if (qrd->preserve_sharp) {
|
||||
field.flag_preserve_sharp = 1;
|
||||
}
|
||||
@@ -106,6 +112,7 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
|
||||
/* Copy mesh to quadriflow data structures. */
|
||||
std::vector<Vector3d> positions;
|
||||
std::vector<uint32_t> indices;
|
||||
std::vector<uint32_t> eflags;
|
||||
std::vector<ObjVertex> vertices;
|
||||
|
||||
for (int i = 0; i < qrd->totverts; i++) {
|
||||
@@ -114,16 +121,18 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
|
||||
}
|
||||
|
||||
for (int q = 0; q < qrd->totfaces; q++) {
|
||||
Vector3i f(qrd->faces[q * 3], qrd->faces[q * 3 + 1], qrd->faces[q * 3 + 2]);
|
||||
Vector3i f(qrd->faces[q].v[0], qrd->faces[q].v[1], qrd->faces[q].v[2]);
|
||||
|
||||
ObjVertex tri[6];
|
||||
int nVertices = 3;
|
||||
const int nVertices = 3;
|
||||
|
||||
tri[0] = ObjVertex(f[0]);
|
||||
tri[1] = ObjVertex(f[1]);
|
||||
tri[2] = ObjVertex(f[2]);
|
||||
|
||||
for (int i = 0; i < nVertices; ++i) {
|
||||
eflags.push_back(qrd->faces[q].eflag[i]);
|
||||
|
||||
const ObjVertex &v = tri[i];
|
||||
VertexMap::const_iterator it = vertexMap.find(v);
|
||||
if (it == vertexMap.end()) {
|
||||
@@ -138,7 +147,10 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
|
||||
}
|
||||
|
||||
field.F.resize(3, indices.size() / 3);
|
||||
// field.FF.resize(3, indices.size() / 3);
|
||||
|
||||
memcpy(field.F.data(), indices.data(), sizeof(uint32_t) * indices.size());
|
||||
// memcpy(field.FF.data(), eflags.data(), sizeof(uint32_t) * eflags.size());
|
||||
|
||||
field.V.resize(3, vertices.size());
|
||||
for (uint32_t i = 0; i < vertices.size(); ++i) {
|
||||
@@ -157,12 +169,17 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
|
||||
return;
|
||||
}
|
||||
|
||||
const int steps = 2;
|
||||
|
||||
/* Setup mesh boundary constraints if needed */
|
||||
if (field.flag_preserve_boundary) {
|
||||
#if 0
|
||||
if (true) { // field.flag_preserve_boundary) {
|
||||
Hierarchy &mRes = field.hierarchy;
|
||||
mRes.clearConstraints();
|
||||
|
||||
for (uint32_t i = 0; i < 3 * mRes.mF.cols(); ++i) {
|
||||
if (mRes.mE2E[i] == -1) {
|
||||
if (mRes.mFF((i) % 3, i / 3) & QFLOW_CONSTRAINED) {
|
||||
// if (mRes.mE2E[i] == -1) {
|
||||
uint32_t i0 = mRes.mF(i % 3, i / 3);
|
||||
uint32_t i1 = mRes.mF((i + 1) % 3, i / 3);
|
||||
Vector3d p0 = mRes.mV[0].col(i0), p1 = mRes.mV[0].col(i1);
|
||||
@@ -172,15 +189,20 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
|
||||
mRes.mCO[0].col(i0) = p0;
|
||||
mRes.mCO[0].col(i1) = p1;
|
||||
mRes.mCQ[0].col(i0) = mRes.mCQ[0].col(i1) = edge;
|
||||
mRes.mCQw[0][i0] = mRes.mCQw[0][i1] = mRes.mCOw[0][i0] = mRes.mCOw[0][i1] = 1.0;
|
||||
mRes.mCQw[0][i0] = mRes.mCQw[0][i1] = mRes.mCOw[0][i0] = mRes.mCOw[0][i1] = 0.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
mRes.propagateConstraints();
|
||||
for (int j = 0; j < 10; j++) {
|
||||
mRes.propagateConstraints();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Optimize the mesh field orientations (tangental field etc) */
|
||||
Optimizer::optimize_orientations(field.hierarchy);
|
||||
for (int i = 0; i < steps; i++) {
|
||||
Optimizer::optimize_orientations(field.hierarchy);
|
||||
}
|
||||
field.ComputeOrientationSingularities();
|
||||
|
||||
if (check_if_canceled(0.3f, update_cb, update_cb_data)) {
|
||||
@@ -195,11 +217,13 @@ void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
|
||||
return;
|
||||
}
|
||||
|
||||
Optimizer::optimize_scale(field.hierarchy, field.rho, field.flag_adaptive_scale);
|
||||
field.flag_adaptive_scale = 1;
|
||||
|
||||
Optimizer::optimize_positions(field.hierarchy, field.flag_adaptive_scale);
|
||||
for (int i = 0; i < steps; i++) {
|
||||
Optimizer::optimize_scale(field.hierarchy, field.rho, field.flag_adaptive_scale);
|
||||
}
|
||||
|
||||
for (int i = 0; i < steps; i++) {
|
||||
Optimizer::optimize_positions(field.hierarchy, field.flag_adaptive_scale);
|
||||
}
|
||||
field.ComputePositionSingularities();
|
||||
|
||||
if (check_if_canceled(0.5f, update_cb, update_cb_data)) {
|
||||
|
@@ -23,9 +23,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum { QFLOW_CONSTRAINED = 1 };
|
||||
|
||||
typedef struct QuadriflowFace {
|
||||
int v[3];
|
||||
char eflag[3];
|
||||
} QuadriflowFace;
|
||||
|
||||
typedef struct QuadriflowRemeshData {
|
||||
float *verts;
|
||||
int *faces;
|
||||
QuadriflowFace *faces;
|
||||
int totfaces;
|
||||
int totverts;
|
||||
|
||||
|
BIN
release/datafiles/icons/brush.sculpt.array.dat
Normal file
BIN
release/datafiles/icons/brush.sculpt.array.dat
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
release/datafiles/icons/brush.sculpt.fairing.dat
Normal file
BIN
release/datafiles/icons/brush.sculpt.fairing.dat
Normal file
Binary file not shown.
BIN
release/datafiles/icons/brush.sculpt.paint.dat
Normal file
BIN
release/datafiles/icons/brush.sculpt.paint.dat
Normal file
Binary file not shown.
BIN
release/datafiles/icons/brush.sculpt.scene_project.dat
Normal file
BIN
release/datafiles/icons/brush.sculpt.scene_project.dat
Normal file
Binary file not shown.
BIN
release/datafiles/icons/brush.sculpt.smear.dat
Normal file
BIN
release/datafiles/icons/brush.sculpt.smear.dat
Normal file
Binary file not shown.
BIN
release/datafiles/icons/brush.sculpt.vcol_boundary.dat
Normal file
BIN
release/datafiles/icons/brush.sculpt.vcol_boundary.dat
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Submodule release/datafiles/locale updated: 62e82958a7...94c39b5832
Submodule release/scripts/addons updated: 4475cbd11a...e7f2213435
Submodule release/scripts/addons_contrib updated: 788441f293...42da56aa73
@@ -4299,6 +4299,28 @@ def km_curve(params):
|
||||
|
||||
# Radial control setup helpers, this operator has a lot of properties.
|
||||
|
||||
def radial_control_properties_channels(paint, prop, secondary_prop, secondary_rotation=False, color=False, zoom=False, type="float"):
|
||||
brush_path = 'tool_settings.' + paint + '.brush'
|
||||
channels_path = brush_path + ".channels.channels"
|
||||
unified = "tool_settings." + paint + ".channels.channels"
|
||||
|
||||
rotation = 'mask_texture_slot_angle' if secondary_rotation else 'texture_slot_angle'
|
||||
return {
|
||||
"properties": [
|
||||
("data_path_primary", '%s["%s"].%s_value' % (channels_path, prop, type)),
|
||||
("data_path_secondary", '%s["%s"].%s_value' % (unified, prop, type) if secondary_prop else ''),
|
||||
("use_secondary", '%s["%s"].inherit' % (channels_path, prop) if secondary_prop else ''),
|
||||
#("rotation_path", '%s["%s"].float_value' % (channels_path, rotation)),
|
||||
#("color_path", brush_path + '.cursor_color_add'),
|
||||
#("fill_color_path", brush_path + '.color' if color else ''),
|
||||
#("fill_color_override_path", unified_path + '.color' if color else ''),
|
||||
#("fill_color_override_test_path", unified_path + '.use_unified_color' if color else ''),
|
||||
#("zoom_path", 'space_data.zoom' if zoom else ''),
|
||||
#("image_id", brush_path + ''),
|
||||
#("secondary_tex", secondary_rotation),
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def radial_control_properties(paint, prop, secondary_prop, secondary_rotation=False, color=False, zoom=False):
|
||||
brush_path = 'tool_settings.' + paint + '.brush'
|
||||
@@ -4348,6 +4370,32 @@ def _template_paint_radial_control(paint, rotation=False, secondary_rotation=Fal
|
||||
return items
|
||||
|
||||
|
||||
def _template_paint_radial_control_channels(paint, rotation=False, secondary_rotation=False, color=False, zoom=False):
|
||||
items = []
|
||||
|
||||
items.extend([
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS'},
|
||||
radial_control_properties_channels(paint, 'radius', 'use_unified_size', type="float", secondary_rotation=secondary_rotation, color=color, zoom=zoom)),
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "shift": True},
|
||||
radial_control_properties_channels(paint, 'strength', 'use_unified_strength', type="factor", secondary_rotation=secondary_rotation, color=color)),
|
||||
])
|
||||
|
||||
"""
|
||||
if rotation:
|
||||
items.extend([
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "ctrl": True},
|
||||
radial_control_properties_channels(paint, 'texture_slot_angle', None, color=color)),
|
||||
])
|
||||
|
||||
if secondary_rotation:
|
||||
items.extend([
|
||||
("wm.radial_control", {"type": 'F', "value": 'PRESS', "ctrl": True, "alt": True},
|
||||
radial_control_properties_channels(paint, 'mask_texture_slot_angle', None, secondary_rotation=secondary_rotation, color=color)),
|
||||
])
|
||||
"""
|
||||
|
||||
return items
|
||||
|
||||
def km_image_paint(params):
|
||||
items = []
|
||||
keymap = (
|
||||
@@ -4515,6 +4563,9 @@ def km_sculpt(params):
|
||||
{"properties": [("mode", 'INVERT')]}),
|
||||
("sculpt.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("mode", 'SMOOTH')]}),
|
||||
# Face Set by Topology
|
||||
("sculpt.face_set_by_topology", {"type": 'W', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("mode", "POLY_LOOP"), ("repeat_previous", True)]}),
|
||||
# Expand
|
||||
("sculpt.expand", {"type": 'A', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("target", "MASK"), ("falloff_type", "GEODESIC"), ("invert", True)]}),
|
||||
@@ -4524,6 +4575,8 @@ def km_sculpt(params):
|
||||
{"properties": [("target", "FACE_SETS"), ("falloff_type", "GEODESIC"), ("invert", False), ("use_modify_active", False)]}),
|
||||
("sculpt.expand", {"type": 'W', "value": 'PRESS', "shift": True, "alt": True},
|
||||
{"properties": [("target", "FACE_SETS"), ("falloff_type", "BOUNDARY_FACE_SET"),("invert", False), ("use_modify_active", True)]}),
|
||||
("sculpt.expand", {"type": 'W', "value": 'PRESS', "shift": True, "ctrl": True},
|
||||
{"properties": [("target", "FACE_SETS"), ("falloff_type", "POLY_LOOP"), ("invert", False), ("use_modify_active", False)]}),
|
||||
# Partial Visibility Show/hide
|
||||
("sculpt.face_set_change_visibility", {"type": 'H', "value": 'PRESS'},
|
||||
{"properties": [("mode", 'TOGGLE')]}),
|
||||
@@ -4531,10 +4584,6 @@ def km_sculpt(params):
|
||||
{"properties": [("mode", 'HIDE_ACTIVE')]}),
|
||||
("sculpt.face_set_change_visibility", {"type": 'H', "value": 'PRESS', "alt": True},
|
||||
{"properties": [("mode", 'SHOW_ALL')]}),
|
||||
("sculpt.face_set_edit", {"type": 'W', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("mode", 'GROW')]}),
|
||||
("sculpt.face_set_edit", {"type": 'W', "value": 'PRESS', "ctrl": True, "alt": True},
|
||||
{"properties": [("mode", 'SHRINK')]}),
|
||||
# Subdivision levels
|
||||
*_template_items_object_subdivision_set(),
|
||||
("object.subdivision_set", {"type": 'PAGE_UP', "value": 'PRESS', "repeat": True},
|
||||
@@ -4566,7 +4615,8 @@ def km_sculpt(params):
|
||||
{"properties": [("scalar", 0.9)]}),
|
||||
("brush.scale_size", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "repeat": True},
|
||||
{"properties": [("scalar", 1.0 / 0.9)]}),
|
||||
*_template_paint_radial_control("sculpt", rotation=True),
|
||||
*_template_paint_radial_control_channels("sculpt", rotation=True),
|
||||
#*_template_paint_radial_control("sculpt", rotation=True),
|
||||
# Stencil
|
||||
("brush.stencil_control", {"type": 'RIGHTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("mode", 'TRANSLATION')]}),
|
||||
@@ -5640,7 +5690,8 @@ def km_sculpt_expand_modal(_params):
|
||||
("FALLOFF_TOPOLOGY", {"type": 'TWO', "value": 'PRESS', "any": True}, None),
|
||||
("FALLOFF_TOPOLOGY_DIAGONALS", {"type": 'THREE', "value": 'PRESS', "any": True}, None),
|
||||
("FALLOFF_SPHERICAL", {"type": 'FOUR', "value": 'PRESS', "any": True}, None),
|
||||
("SNAP_TOGGLE", {"type": 'LEFT_CTRL', "value": 'ANY'}, None),
|
||||
("SNAP_ENABLE", {"type": 'LEFT_CTRL', "value": 'PRESS'}, None),
|
||||
("SNAP_DISABLE", {"type": 'LEFT_CTRL', "value": 'RELEASE'}, None),
|
||||
("LOOP_COUNT_INCREASE", {"type": 'W', "value": 'PRESS', "any": True, "repeat": True}, None),
|
||||
("LOOP_COUNT_DECREASE", {"type": 'Q', "value": 'PRESS', "any": True, "repeat": True}, None),
|
||||
("BRUSH_GRADIENT_TOGGLE", {"type": 'B', "value": 'PRESS', "any": True}, None),
|
||||
@@ -6628,6 +6679,26 @@ def km_3d_view_tool_sculpt_line_project(params):
|
||||
]},
|
||||
)
|
||||
|
||||
def km_3d_view_tool_sculpt_lasso_project(params):
|
||||
return (
|
||||
"3D View Tool: Sculpt, Lasso Project",
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
("sculpt.project_lasso_gesture", {"type": params.tool_tweak, "value": 'ANY'},
|
||||
None),
|
||||
]},
|
||||
)
|
||||
|
||||
def km_3d_view_tool_sculpt_box_project(params):
|
||||
return (
|
||||
"3D View Tool: Sculpt, Box Project",
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
("sculpt.project_box_gesture", {"type": params.tool_tweak, "value": 'ANY'},
|
||||
None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
def km_3d_view_tool_sculpt_mesh_filter(params):
|
||||
return (
|
||||
@@ -6639,6 +6710,16 @@ def km_3d_view_tool_sculpt_mesh_filter(params):
|
||||
]},
|
||||
)
|
||||
|
||||
def km_3d_view_tool_sculpt_ipmask_filter(params):
|
||||
return (
|
||||
"3D View Tool: Sculpt, IPMask Filter",
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
("sculpt.ipmask_filter", {"type": params.tool_tweak, "value": 'ANY'},
|
||||
None)
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
def km_3d_view_tool_sculpt_cloth_filter(params):
|
||||
return (
|
||||
@@ -7256,7 +7337,10 @@ def generate_keymaps(params=None):
|
||||
km_3d_view_tool_sculpt_lasso_trim(params),
|
||||
km_3d_view_tool_sculpt_line_mask(params),
|
||||
km_3d_view_tool_sculpt_line_project(params),
|
||||
km_3d_view_tool_sculpt_lasso_project(params),
|
||||
km_3d_view_tool_sculpt_box_project(params),
|
||||
km_3d_view_tool_sculpt_mesh_filter(params),
|
||||
km_3d_view_tool_sculpt_ipmask_filter(params),
|
||||
km_3d_view_tool_sculpt_cloth_filter(params),
|
||||
km_3d_view_tool_sculpt_color_filter(params),
|
||||
km_3d_view_tool_sculpt_mask_by_color(params),
|
||||
|
@@ -522,6 +522,7 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
|
||||
col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
|
||||
col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
|
||||
col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
|
||||
col.prop(mesh, "use_remesh_preserve_materials", text="Materials")
|
||||
if context.preferences.experimental.use_sculpt_vertex_colors:
|
||||
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
|
||||
|
||||
|
@@ -19,6 +19,16 @@
|
||||
# <pep8 compliant>
|
||||
from bpy.types import Menu
|
||||
|
||||
channel_name_map = {
|
||||
"size" : "radius",
|
||||
"autosmooth_fset_slide":"fset_slide",
|
||||
"auto_smooth_factor": "autosmooth",
|
||||
"auto_smooth_projection": "autosmooth_projection",
|
||||
"auto_smooth_radius_factor": "autosmooth_radius_scale",
|
||||
"boundary_smooth_factor": "boundary_smooth",
|
||||
"autosmooth_fset_slide": "fset_slide",
|
||||
"topology_rake_factor": "topology_rake"
|
||||
};
|
||||
|
||||
class UnifiedPaintPanel:
|
||||
# subclass must set
|
||||
@@ -97,6 +107,136 @@ class UnifiedPaintPanel:
|
||||
return tool_settings.gpencil_vertex_paint
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None,
|
||||
slider=False, header=False, expand=None, toolsettings_only=False):
|
||||
""" Generalized way of adding brush options to the UI,
|
||||
along with their pen pressure setting and global toggle, if they exist. """
|
||||
ch = brush.channels.channels[prop_name]
|
||||
finalch = ch
|
||||
|
||||
l1 = layout
|
||||
|
||||
#if ch.ui_expanded:
|
||||
# layout = layout.box().column() #.column() is a bit more compact
|
||||
|
||||
if ch.type == "BITMASK":
|
||||
layout = layout.box()
|
||||
|
||||
row = layout.row(align=True)
|
||||
|
||||
typeprop = "float_value"
|
||||
|
||||
if ch.type == "INT":
|
||||
typeprop = "int_value"
|
||||
elif ch.type == "BOOL":
|
||||
typeprop = "bool_value"
|
||||
elif ch.type == "ENUM":
|
||||
typeprop = "enum_value"
|
||||
elif ch.type == "BITMASK":
|
||||
typeprop = "flags_value"
|
||||
elif ch.type == "VEC3":
|
||||
typeprop = "color3_value"
|
||||
elif ch.type == "VEC4":
|
||||
typeprop = "color4_value"
|
||||
|
||||
if text is None:
|
||||
s = prop_name.lower().replace("_", " ").split(" ");
|
||||
text = ''
|
||||
for k in s:
|
||||
text += k[0].upper() + k[1:] + " "
|
||||
text = text.strip()
|
||||
|
||||
path = ""
|
||||
is_toolset = False
|
||||
|
||||
if ch.inherit or toolsettings_only:
|
||||
sd = context.tool_settings.sculpt
|
||||
#ensure channel exists in tool settings channel set
|
||||
sd.channels.ensure(ch)
|
||||
|
||||
finalch = sd.channels.channels[prop_name]
|
||||
is_toolset = True
|
||||
path = "tool_settings.sculpt.channels.channels[\"%s\"]" % ch.idname
|
||||
else:
|
||||
path = "tool_settings.sculpt.brush.channels.channels[\"%s\"]" % ch.idname
|
||||
|
||||
if ch.type == "BITMASK":
|
||||
row.label(text=text)
|
||||
|
||||
if header:
|
||||
row.prop_menu_enum(finalch, typeprop)
|
||||
else:
|
||||
col = layout.column()
|
||||
col.emboss = "NONE"
|
||||
for item in finalch.enum_items:
|
||||
if item.identifier in finalch.flags_value:
|
||||
itemicon = "CHECKBOX_HLT"
|
||||
else:
|
||||
itemicon = "CHECKBOX_DEHLT"
|
||||
col.prop_enum(finalch, typeprop, item.identifier, icon=itemicon)
|
||||
|
||||
elif expand is not None:
|
||||
row.prop(finalch, typeprop, icon=icon, text=text, slider=slider, expand=expand)
|
||||
else:
|
||||
row.prop(finalch, typeprop, icon=icon, text=text, slider=slider)
|
||||
|
||||
pressure = pressure and ch.type not in ["BOOL", "ENUM", "BITMASK"]
|
||||
|
||||
if pressure:
|
||||
row.prop(finalch.mappings["PRESSURE"], "enabled", text="", icon="STYLUS_PRESSURE")
|
||||
#if pressure_name:
|
||||
# row.prop(brush, pressure_name, text="")
|
||||
|
||||
#if unified_name and not header:
|
||||
# # NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281
|
||||
# row.prop(ups, unified_name, text="", icon='BRUSHES_ALL')
|
||||
if not header and ch.type != "BOOL":
|
||||
if ch.type == "BITMASK" and not toolsettings_only and ch == finalch:
|
||||
row.prop(ch, "inherit_if_unset", text="Combine With Defaults")
|
||||
|
||||
if not toolsettings_only:
|
||||
row.prop(ch, "inherit", text="", icon='BRUSHES_ALL')
|
||||
|
||||
if ch.type == "BITMASK":
|
||||
return
|
||||
|
||||
row.prop(ch, "ui_expanded", text="", icon="TRIA_DOWN" if ch.ui_expanded else "TRIA_RIGHT")
|
||||
|
||||
if ch.ui_expanded:
|
||||
for mp in finalch.mappings:
|
||||
row2 = layout.row()
|
||||
name = mp.type.lower()
|
||||
|
||||
if len(name) > 0:
|
||||
name = name[0].upper() + name[1:]
|
||||
else:
|
||||
name = "name error"
|
||||
|
||||
row2.label(text=name)
|
||||
row2.prop(mp, "enabled", text="", icon="STYLUS_PRESSURE")
|
||||
row2.prop(mp, "ui_expanded", text="", icon="TRIA_DOWN" if mp.ui_expanded else "TRIA_RIGHT")
|
||||
|
||||
if mp.ui_expanded:
|
||||
layout.template_curve_mapping(mp, "curve", brush=True)
|
||||
|
||||
col = layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
|
||||
path2 = path + ".mappings[\"%s\"].curve" % (mp.type)
|
||||
|
||||
shapes = ['SMOOTH', 'ROUND', 'ROOT', 'SHARP', 'LINE', 'MAX']
|
||||
icons = ['SMOOTHCURVE', 'SPHERECURVE', 'ROOTCURVE', 'SHARPCURVE', 'LINCURVE', 'NOCURVE']
|
||||
|
||||
for i, shape in enumerate(shapes):
|
||||
props = row.operator("brush.curve_preset_load", icon=icons[i], text="")
|
||||
props.shape = shape
|
||||
props.path = path2
|
||||
|
||||
#row2.prop(mp, "curve")
|
||||
|
||||
return row
|
||||
|
||||
@staticmethod
|
||||
def prop_unified(
|
||||
layout,
|
||||
@@ -112,6 +252,14 @@ class UnifiedPaintPanel:
|
||||
):
|
||||
""" Generalized way of adding brush options to the UI,
|
||||
along with their pen pressure setting and global toggle, if they exist. """
|
||||
|
||||
if prop_name in channel_name_map:
|
||||
prop_name = channel_name_map[prop_name]
|
||||
|
||||
if prop_name in brush.channels.channels:
|
||||
# def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None, slider=False, header=False):
|
||||
return UnifiedPaintPanel.channel_unified(layout, context, brush, prop_name, icon=icon, text=text, slider=slider, header=header)
|
||||
|
||||
row = layout.row(align=True)
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
prop_owner = brush
|
||||
@@ -131,6 +279,12 @@ class UnifiedPaintPanel:
|
||||
|
||||
@staticmethod
|
||||
def prop_unified_color(parent, context, brush, prop_name, *, text=None):
|
||||
if context.mode == 'SCULPT':
|
||||
# def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None,
|
||||
# slider=False, header=False, expand=None, toolsettings_only=False):
|
||||
return UnifiedPaintPanel.channel_unified(parent, context, brush, prop_name, text=text)
|
||||
|
||||
|
||||
ups = context.tool_settings.unified_paint_settings
|
||||
prop_owner = ups if ups.use_unified_color else brush
|
||||
parent.prop(prop_owner, prop_name, text=text)
|
||||
@@ -549,15 +703,27 @@ def brush_settings(layout, context, brush, popover=False):
|
||||
if context.preferences.experimental.use_sculpt_tools_tilt and capabilities.has_tilt:
|
||||
layout.prop(brush, "tilt_strength_factor", slider=True)
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"hard_edge_mode",
|
||||
slider=True,
|
||||
unified_name="use_unified_hard_edge_mode",
|
||||
)
|
||||
|
||||
row = layout.row(align=True)
|
||||
|
||||
row.prop(brush, "hardness", slider=True)
|
||||
row.prop(brush, "invert_hardness_pressure", text="")
|
||||
row.prop(brush, "use_hardness_pressure", text="")
|
||||
|
||||
# auto_smooth_factor and use_inverse_smooth_pressure
|
||||
if capabilities.has_auto_smooth:
|
||||
box = layout.box().column() #.column() is a bit more compact
|
||||
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
box,
|
||||
context,
|
||||
brush,
|
||||
"auto_smooth_factor",
|
||||
@@ -565,13 +731,83 @@ def brush_settings(layout, context, brush, popover=False):
|
||||
slider=True,
|
||||
)
|
||||
|
||||
# topology_rake_factor
|
||||
#box.prop(brush, "boundary_smooth_factor")
|
||||
#box.prop(brush, "use_weighted_smooth")
|
||||
#box.prop(brush, "preserve_faceset_boundary")
|
||||
|
||||
UnifiedPaintPanel.prop_unified(box, context, brush, "boundary_smooth_factor", slider=True)
|
||||
UnifiedPaintPanel.prop_unified(box, context, brush, "use_weighted_smooth")
|
||||
UnifiedPaintPanel.prop_unified(box, context, brush, "preserve_faceset_boundary")
|
||||
|
||||
if 1: #brush.preserve_faceset_boundary:
|
||||
UnifiedPaintPanel.prop_unified(box, context, brush, "autosmooth_fset_slide", slider=True)
|
||||
#box.prop(brush, "autosmooth_fset_slide")
|
||||
|
||||
box.prop(brush, "use_custom_auto_smooth_spacing", text="Custom Spacing")
|
||||
if brush.use_custom_auto_smooth_spacing:
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
box,
|
||||
context,
|
||||
brush,
|
||||
"auto_smooth_spacing",
|
||||
slider=True,
|
||||
text="Spacing"
|
||||
)
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
box,
|
||||
context,
|
||||
brush,
|
||||
"auto_smooth_projection",
|
||||
slider=True
|
||||
)
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
box,
|
||||
context,
|
||||
brush,
|
||||
"auto_smooth_radius_factor",
|
||||
slider=True
|
||||
)
|
||||
elif brush.sculpt_tool == "SMOOTH":
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"auto_smooth_projection",
|
||||
slider=True
|
||||
)
|
||||
|
||||
|
||||
if capabilities.has_vcol_boundary_smooth:
|
||||
layout.prop(brush, "vcol_boundary_factor", slider=True)
|
||||
|
||||
if (
|
||||
capabilities.has_topology_rake and
|
||||
context.sculpt_object.use_dynamic_topology_sculpting
|
||||
):
|
||||
layout.prop(brush, "topology_rake_factor", slider=True)
|
||||
box = layout.box().column() #.column() is a bit more compact
|
||||
|
||||
#box.prop(brush, "topology_rake_factor", slider=True)
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
box,
|
||||
context,
|
||||
brush,
|
||||
"topology_rake_factor",
|
||||
slider=True,
|
||||
text="Topology Rake"
|
||||
)
|
||||
box.prop(brush, "use_custom_topology_rake_spacing", text="Custom Spacing")
|
||||
|
||||
if brush.use_custom_topology_rake_spacing:
|
||||
box.prop(brush, "topology_rake_spacing", text="Spacing")
|
||||
box.prop(brush, "topology_rake_projection")
|
||||
|
||||
box.prop(brush, "topology_rake_radius_factor", slider=True)
|
||||
box.prop(brush, "use_curvature_rake")
|
||||
box.prop(brush, "ignore_falloff_for_topology_rake")
|
||||
|
||||
if context.sculpt_object.use_dynamic_topology_sculpting:
|
||||
layout.prop(brush.dyntopo, "disabled", text="Disable Dyntopo")
|
||||
|
||||
# normal_weight
|
||||
if capabilities.has_normal_weight:
|
||||
layout.prop(brush, "normal_weight", slider=True)
|
||||
@@ -620,16 +856,27 @@ def brush_settings(layout, context, brush, popover=False):
|
||||
|
||||
if capabilities.has_color:
|
||||
ups = context.scene.tool_settings.unified_paint_settings
|
||||
row = layout.row(align=True)
|
||||
|
||||
if context.mode == "SCULPT":
|
||||
row = layout.column(align=True)
|
||||
else:
|
||||
row = layout.row(align=True)
|
||||
|
||||
UnifiedPaintPanel.prop_unified_color(row, context, brush, "color", text="")
|
||||
UnifiedPaintPanel.prop_unified_color(row, context, brush, "secondary_color", text="")
|
||||
row.separator()
|
||||
row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="", emboss=False)
|
||||
row.prop(ups, "use_unified_color", text="", icon='BRUSHES_ALL')
|
||||
|
||||
if context.mode != "SCULPT":
|
||||
row.separator()
|
||||
row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="", emboss=False)
|
||||
row.prop(ups, "use_unified_color", text="", icon='BRUSHES_ALL')
|
||||
layout.prop(brush, "blend", text="Blend Mode")
|
||||
|
||||
# Per sculpt tool options.
|
||||
|
||||
if sculpt_tool == "VCOL_BOUNDARY":
|
||||
row = layout.row()
|
||||
row.prop(brush, "vcol_boundary_exponent")
|
||||
|
||||
if sculpt_tool == 'CLAY_STRIPS':
|
||||
row = layout.row()
|
||||
row.prop(brush, "tip_roundness")
|
||||
@@ -638,6 +885,7 @@ def brush_settings(layout, context, brush, popover=False):
|
||||
layout.separator()
|
||||
layout.prop(brush, "elastic_deform_type")
|
||||
layout.prop(brush, "elastic_deform_volume_preservation", slider=True)
|
||||
layout.prop(brush, "use_surface_falloff")
|
||||
layout.separator()
|
||||
|
||||
elif sculpt_tool == 'SNAKE_HOOK':
|
||||
@@ -701,6 +949,7 @@ def brush_settings(layout, context, brush, popover=False):
|
||||
elif sculpt_tool == 'GRAB':
|
||||
layout.prop(brush, "use_grab_active_vertex")
|
||||
layout.prop(brush, "use_grab_silhouette")
|
||||
layout.prop(brush, "use_surface_falloff")
|
||||
|
||||
elif sculpt_tool == 'PAINT':
|
||||
row = layout.row(align=True)
|
||||
@@ -754,9 +1003,28 @@ def brush_settings(layout, context, brush, popover=False):
|
||||
col.prop(brush, "use_multiplane_scrape_dynamic")
|
||||
col.prop(brush, "show_multiplane_scrape_planes_preview")
|
||||
|
||||
elif sculpt_tool == 'SCENE_PROJECT':
|
||||
col = layout.column()
|
||||
col.prop(brush, "scene_project_direction_type")
|
||||
|
||||
elif sculpt_tool == 'ARRAY':
|
||||
col = layout.column()
|
||||
col.prop(brush, "array_deform_type")
|
||||
col.prop(brush, "array_count")
|
||||
col.prop(brush, "use_array_lock_orientation")
|
||||
col.prop(brush, "use_array_fill_holes")
|
||||
|
||||
elif sculpt_tool == 'SMOOTH':
|
||||
col = layout.column()
|
||||
col.prop(brush, "boundary_smooth_factor")
|
||||
|
||||
col.prop(brush, "use_weighted_smooth")
|
||||
col.prop(brush, "preserve_faceset_boundary")
|
||||
if brush.preserve_faceset_boundary:
|
||||
col.prop(brush, "autosmooth_fset_slide")
|
||||
|
||||
col.prop(brush, "smooth_deform_type")
|
||||
|
||||
if brush.smooth_deform_type == 'SURFACE':
|
||||
col.prop(brush, "surface_smooth_shape_preservation")
|
||||
col.prop(brush, "surface_smooth_current_vertex")
|
||||
@@ -769,6 +1037,10 @@ def brush_settings(layout, context, brush, popover=False):
|
||||
elif sculpt_tool == 'MASK':
|
||||
layout.row().prop(brush, "mask_tool", expand=True)
|
||||
|
||||
|
||||
layout.template_curve_mapping(brush, "pressure_size_curve")
|
||||
layout.template_curve_mapping(brush, "pressure_strength_curve", brush=True)
|
||||
|
||||
# End sculpt_tool interface.
|
||||
|
||||
# 3D and 2D Texture Paint Mode.
|
||||
@@ -858,7 +1130,21 @@ def brush_shared_settings(layout, context, brush, popover=False):
|
||||
size_prop = "size"
|
||||
if size_mode and (size_owner.use_locked_size == 'SCENE'):
|
||||
size_prop = "unprojected_radius"
|
||||
|
||||
if size or size_mode:
|
||||
if size:
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"radius" if size_prop == "size" else size_prop.upper(),
|
||||
text="Radius",
|
||||
slider=True,
|
||||
)
|
||||
if size_mode:
|
||||
layout.row().prop(size_owner, "use_locked_size", expand=True)
|
||||
layout.separator()
|
||||
elif size or size_mode:
|
||||
if size:
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
@@ -874,7 +1160,16 @@ def brush_shared_settings(layout, context, brush, popover=False):
|
||||
layout.row().prop(size_owner, "use_locked_size", expand=True)
|
||||
layout.separator()
|
||||
|
||||
if strength:
|
||||
if strength:
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"strength",
|
||||
slider=True
|
||||
)
|
||||
layout.separator()
|
||||
elif strength:
|
||||
pressure_name = "use_pressure_strength" if strength_pressure else None
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
@@ -886,9 +1181,13 @@ def brush_shared_settings(layout, context, brush, popover=False):
|
||||
slider=True,
|
||||
)
|
||||
layout.separator()
|
||||
|
||||
if direction:
|
||||
layout.row().prop(brush, "direction", expand=True)
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"direction", expand=True)
|
||||
#layout.row().prop(brush, "direction", expand=True)
|
||||
|
||||
|
||||
def brush_settings_advanced(layout, context, brush, popover=False):
|
||||
@@ -911,11 +1210,31 @@ def brush_settings_advanced(layout, context, brush, popover=False):
|
||||
use_accumulate = capabilities.has_accumulate
|
||||
use_frontface = True
|
||||
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout.column(),
|
||||
context,
|
||||
brush,
|
||||
"automasking", expand=False)
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout.column(),
|
||||
context,
|
||||
brush,
|
||||
"automasking_boundary_edges_propagation_steps")
|
||||
|
||||
"""
|
||||
col = layout.column(heading="Auto-Masking", align=True)
|
||||
|
||||
# topology automasking
|
||||
col.prop(brush, "use_automasking_topology", text="Topology")
|
||||
|
||||
col.prop(brush, "use_automasking_concave")
|
||||
|
||||
col2 = col.column()
|
||||
col2.enabled = brush.use_automasking_concave
|
||||
|
||||
col2.prop(brush, "concave_mask_factor", text="Cavity Factor")
|
||||
col2.prop(brush, "invert_automasking_concavity", text="Invert Cavity Mask")
|
||||
|
||||
# face masks automasking
|
||||
col.prop(brush, "use_automasking_face_sets", text="Face Sets")
|
||||
|
||||
@@ -923,6 +1242,7 @@ def brush_settings_advanced(layout, context, brush, popover=False):
|
||||
col.prop(brush, "use_automasking_boundary_edges", text="Mesh Boundary")
|
||||
col.prop(brush, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
||||
col.prop(brush, "automasking_boundary_edges_propagation_steps")
|
||||
"""
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@@ -279,9 +279,16 @@ class _defs_annotate:
|
||||
|
||||
class _defs_transform:
|
||||
|
||||
def draw_transform_sculpt_tool_settings(context, layout):
|
||||
if context.mode != 'SCULPT':
|
||||
return
|
||||
layout.prop(context.tool_settings.sculpt, "transform_deform_target")
|
||||
layout.prop(context.tool_settings.sculpt, "transform_mode")
|
||||
|
||||
@ToolDef.from_fn
|
||||
def translate():
|
||||
def draw_settings(context, layout, _tool):
|
||||
_defs_transform.draw_transform_sculpt_tool_settings(context, layout)
|
||||
_template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 1)
|
||||
return dict(
|
||||
idname="builtin.move",
|
||||
@@ -297,6 +304,7 @@ class _defs_transform:
|
||||
@ToolDef.from_fn
|
||||
def rotate():
|
||||
def draw_settings(context, layout, _tool):
|
||||
_defs_transform.draw_transform_sculpt_tool_settings(context, layout)
|
||||
_template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 2)
|
||||
return dict(
|
||||
idname="builtin.rotate",
|
||||
@@ -312,6 +320,7 @@ class _defs_transform:
|
||||
@ToolDef.from_fn
|
||||
def scale():
|
||||
def draw_settings(context, layout, _tool):
|
||||
_defs_transform.draw_transform_sculpt_tool_settings(context, layout)
|
||||
_template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 3)
|
||||
return dict(
|
||||
idname="builtin.scale",
|
||||
@@ -367,6 +376,7 @@ class _defs_transform:
|
||||
props = tool.gizmo_group_properties("VIEW3D_GGT_xform_gizmo")
|
||||
layout.prop(props, "drag_action")
|
||||
|
||||
_defs_transform.draw_transform_sculpt_tool_settings(context, layout)
|
||||
_template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 1)
|
||||
|
||||
return dict(
|
||||
@@ -1294,7 +1304,9 @@ class _defs_sculpt:
|
||||
# Use 'bpy.context' instead of 'context' since it can be None.
|
||||
prefs = bpy.context.preferences
|
||||
if not prefs.experimental.use_sculpt_vertex_colors:
|
||||
exclude_filter = {'PAINT', 'SMEAR'}
|
||||
exclude_filter = {'PAINT' : True, 'SMEAR' : True}
|
||||
if not prefs.experimental.use_sculpt_uvsmooth:
|
||||
exclude_filter['UV_SMOOTH'] = True
|
||||
|
||||
return generate_from_enum_ex(
|
||||
context,
|
||||
@@ -1412,6 +1424,7 @@ class _defs_sculpt:
|
||||
props = tool.operator_properties("sculpt.trim_lasso_gesture")
|
||||
layout.prop(props, "trim_mode", expand=False)
|
||||
layout.prop(props, "trim_orientation", expand=False)
|
||||
layout.prop(props, "trim_location", expand=False)
|
||||
layout.prop(props, "use_cursor_depth", expand=False)
|
||||
return dict(
|
||||
idname="builtin.lasso_trim",
|
||||
@@ -1426,6 +1439,7 @@ class _defs_sculpt:
|
||||
def project_line():
|
||||
def draw_settings(_context, layout, tool):
|
||||
props = tool.operator_properties("sculpt.project_line_gesture")
|
||||
layout.prop(props, "deformation_mode", expand=False)
|
||||
layout.prop(props, "use_limit_to_segment", expand=False)
|
||||
|
||||
return dict(
|
||||
@@ -1437,6 +1451,26 @@ class _defs_sculpt:
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def project_lasso():
|
||||
return dict(
|
||||
idname="builtin.lasso_project",
|
||||
label="Lasso Project",
|
||||
icon="ops.sculpt.lasso_project",
|
||||
widget=None,
|
||||
keymap=(),
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def project_box():
|
||||
return dict(
|
||||
idname="builtin.box_project",
|
||||
label="Box Project",
|
||||
icon="ops.sculpt.box_project",
|
||||
widget=None,
|
||||
keymap=(),
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def mesh_filter():
|
||||
def draw_settings(_context, layout, tool):
|
||||
@@ -1453,6 +1487,8 @@ class _defs_sculpt:
|
||||
layout.prop(props, "sharpen_smooth_ratio", expand=False)
|
||||
layout.prop(props, "sharpen_intensify_detail_strength", expand=False)
|
||||
layout.prop(props, "sharpen_curvature_smooth_iterations", expand=False)
|
||||
elif props.type == 'SPHERE':
|
||||
layout.prop(props, "sphere_center", expand=False)
|
||||
|
||||
return dict(
|
||||
idname="builtin.mesh_filter",
|
||||
@@ -1463,6 +1499,23 @@ class _defs_sculpt:
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def ipmask_filter():
|
||||
def draw_settings(_context, layout, tool):
|
||||
props = tool.operator_properties("sculpt.ipmask_filter")
|
||||
layout.prop(props, "filter_type", expand=False)
|
||||
layout.prop(props, "iterations", expand=False)
|
||||
layout.prop(props, "use_step_interpolation", expand=False)
|
||||
|
||||
return dict(
|
||||
idname="builtin.ipmask_filter",
|
||||
label="IPMask Filter",
|
||||
icon="ops.sculpt.ipmask_filter",
|
||||
widget=None,
|
||||
keymap=(),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def cloth_filter():
|
||||
def draw_settings(_context, layout, tool):
|
||||
@@ -1471,6 +1524,8 @@ class _defs_sculpt:
|
||||
layout.prop(props, "strength")
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "force_axis")
|
||||
if props.type == "PINCH":
|
||||
layout.prop(props, "pinch_origin", expand=False)
|
||||
layout.prop(props, "orientation", expand=False)
|
||||
layout.prop(props, "cloth_mass")
|
||||
layout.prop(props, "cloth_damping")
|
||||
@@ -2845,10 +2900,15 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
||||
_defs_sculpt.trim_box,
|
||||
_defs_sculpt.trim_lasso,
|
||||
),
|
||||
(
|
||||
_defs_sculpt.project_line,
|
||||
_defs_sculpt.project_box,
|
||||
_defs_sculpt.project_lasso,
|
||||
),
|
||||
None,
|
||||
_defs_sculpt.mesh_filter,
|
||||
_defs_sculpt.cloth_filter,
|
||||
_defs_sculpt.ipmask_filter,
|
||||
lambda context: (
|
||||
(_defs_sculpt.color_filter,)
|
||||
if context is None or (
|
||||
|
@@ -2248,6 +2248,7 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
|
||||
self._draw_items(
|
||||
context, (
|
||||
({"property": "use_sculpt_vertex_colors"}, "T71947"),
|
||||
({"property": "use_sculpt_uvsmooth"}, ""),
|
||||
({"property": "use_sculpt_tools_tilt"}, "T82877"),
|
||||
({"property": "use_extended_asset_browser"}, ("project/view/130/", "Project Page")),
|
||||
({"property": "use_override_templates"}, ("T73318", "Milestone 4")),
|
||||
|
@@ -171,6 +171,7 @@ class VIEW3D_HT_tool_header(Header):
|
||||
row.popover(panel="VIEW3D_PT_tools_weightpaint_symmetry_for_topbar", text="")
|
||||
elif mode_string == 'SCULPT':
|
||||
row.popover(panel="VIEW3D_PT_sculpt_symmetry_for_topbar", text="")
|
||||
layout.prop(context.object.data, "use_fset_boundary_mirror");
|
||||
elif mode_string == 'PAINT_VERTEX':
|
||||
row.popover(panel="VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar", text="")
|
||||
|
||||
@@ -3061,6 +3062,12 @@ class VIEW3D_MT_sculpt(Menu):
|
||||
|
||||
props = layout.operator("object.transfer_mode", text="Transfer Sculpt Mode")
|
||||
props.use_eyedropper = True
|
||||
props.flash_object = False
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("sculpt.reset_brushes")
|
||||
|
||||
|
||||
|
||||
class VIEW3D_MT_mask(Menu):
|
||||
@@ -3699,6 +3706,8 @@ class VIEW3D_MT_edit_mesh(Menu):
|
||||
if with_bullet:
|
||||
layout.operator("mesh.convex_hull")
|
||||
|
||||
layout.operator("mesh.fair_vertices", text="Fair")
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.operator("mesh.symmetrize")
|
||||
@@ -5302,24 +5311,24 @@ class VIEW3D_MT_sculpt_mask_edit_pie(Menu):
|
||||
op = pie.operator("paint.mask_flood_fill", text='Clear Mask')
|
||||
op.mode = 'VALUE'
|
||||
op.value = 0.0
|
||||
op = pie.operator("sculpt.mask_filter", text='Smooth Mask')
|
||||
op.filter_type = 'SMOOTH'
|
||||
op.auto_iteration_count = True
|
||||
op = pie.operator("sculpt.mask_filter", text='Sharpen Mask')
|
||||
op.filter_type = 'SHARPEN'
|
||||
op.auto_iteration_count = True
|
||||
op = pie.operator("sculpt.mask_filter", text='Grow Mask')
|
||||
op.filter_type = 'GROW'
|
||||
op.auto_iteration_count = True
|
||||
op = pie.operator("sculpt.mask_filter", text='Shrink Mask')
|
||||
op.filter_type = 'SHRINK'
|
||||
op.auto_iteration_count = True
|
||||
op = pie.operator("sculpt.mask_filter", text='Increase Contrast')
|
||||
op.filter_type = 'CONTRAST_INCREASE'
|
||||
op.auto_iteration_count = False
|
||||
op = pie.operator("sculpt.mask_filter", text='Decrease Contrast')
|
||||
op.filter_type = 'CONTRAST_DECREASE'
|
||||
op.auto_iteration_count = False
|
||||
|
||||
op = pie.operator("sculpt.ipmask_filter", text='IPMask Smooth')
|
||||
op.filter_type = "SMOOTH_SHARPEN"
|
||||
op.iterations = 1
|
||||
|
||||
op = pie.operator("sculpt.ipmask_filter", text='IPMask Grow')
|
||||
op.filter_type = "GROW_SHRINK"
|
||||
op.iterations = 1
|
||||
|
||||
op = pie.operator("sculpt.ipmask_filter", text='IPMask Harder')
|
||||
op.filter_type = "HARDER_SOFTER"
|
||||
op.iterations = 1
|
||||
|
||||
op = pie.operator("sculpt.ipmask_filter", text='IPMask Contrast')
|
||||
op.filter_type = "CONTRAST"
|
||||
op.iterations = 1
|
||||
|
||||
|
||||
|
||||
|
||||
class VIEW3D_MT_sculpt_automasking_pie(Menu):
|
||||
@@ -5358,6 +5367,18 @@ class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
|
||||
op = pie.operator("sculpt.face_set_change_visibility", text='Show All')
|
||||
op.mode = 'SHOW_ALL'
|
||||
|
||||
op = pie.operator("sculpt.face_sets_init", text='Init by UV Seams')
|
||||
op.mode = 'UV_SEAMS'
|
||||
|
||||
op = pie.operator("sculpt.face_sets_init", text='Init by Loose Parts')
|
||||
op.mode = 'LOOSE_PARTS'
|
||||
|
||||
op = pie.operator("sculpt.face_sets_init", text='Init by Face Sets Boundaries')
|
||||
op.mode = 'FACE_SET_BOUNDARIES'
|
||||
|
||||
op = pie.operator("sculpt.face_sets_create", text='Face Set from Selection')
|
||||
op.mode = 'SELECTION'
|
||||
|
||||
|
||||
class VIEW3D_MT_wpaint_vgroup_lock_pie(Menu):
|
||||
bl_label = "Vertex Group Locks"
|
||||
|
@@ -17,7 +17,7 @@
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from bpy.types import Menu, Panel, UIList, WindowManager
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
GreasePencilSculptOptionsPanel,
|
||||
GreasePencilDisplayPanel,
|
||||
@@ -754,10 +754,78 @@ class VIEW3D_PT_tools_brush_falloff_normal(View3DPaintPanel, Panel):
|
||||
layout.prop(ipaint, "normal_angle", text="Angle")
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_sculpt_dyntopo_advanced(Panel, View3DPaintPanel):
|
||||
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
|
||||
bl_label = "Dyntopo (Advanced)"
|
||||
#bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_ui_units_x = 12
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
paint_settings = cls.paint_settings(context)
|
||||
return (context.sculpt_object and context.tool_settings.sculpt and paint_settings)
|
||||
|
||||
def draw_header(self, context):
|
||||
pass
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
tool_settings = context.tool_settings
|
||||
sculpt = tool_settings.sculpt
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
col = layout.column()
|
||||
col.label(text="Local Brush Settings")
|
||||
|
||||
row = col.row()
|
||||
row.prop(brush.dyntopo, "disabled", text="Disable Dyntopo locally for this brush")
|
||||
|
||||
col.label(text="Overrides")
|
||||
inherit_all = "ALL" in brush.dyntopo.inherit
|
||||
|
||||
col.prop_enum(brush.dyntopo, "inherit", value="ALL", text="Use All Defaults", icon="LOCKED" if inherit_all else "UNLOCKED")
|
||||
|
||||
def do_prop(key):
|
||||
row = col.row()
|
||||
if key.upper() in brush.dyntopo.inherit:
|
||||
icon = "UNLOCKED"
|
||||
else:
|
||||
icon = "LOCKED"
|
||||
|
||||
row.prop_enum(brush.dyntopo, "inherit", value=key.upper(), icon=icon, text="")
|
||||
|
||||
row2 = row.row()
|
||||
row2.prop(brush.dyntopo, key)
|
||||
|
||||
if icon == "UNLOCKED":
|
||||
row2.enabled = False
|
||||
|
||||
if inherit_all:
|
||||
row.enabled = False
|
||||
|
||||
col = layout.column()
|
||||
do_prop("subdivide")
|
||||
do_prop("collapse")
|
||||
do_prop("cleanup")
|
||||
do_prop("spacing")
|
||||
do_prop("local_subdivide")
|
||||
do_prop("local_collapse")
|
||||
do_prop("detail_size")
|
||||
do_prop("detail_range")
|
||||
do_prop("detail_percent")
|
||||
do_prop("constant_detail")
|
||||
do_prop("mode")
|
||||
do_prop("radius_scale")
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
|
||||
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
|
||||
bl_label = "Dyntopo"
|
||||
bl_label = "Dynamic Mode"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_ui_units_x = 12
|
||||
|
||||
@@ -789,6 +857,8 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
|
||||
col = layout.column()
|
||||
col.active = context.sculpt_object.use_dynamic_topology_sculpting
|
||||
|
||||
col.prop(sculpt, "use_dyntopo");
|
||||
|
||||
sub = col.column()
|
||||
sub.active = (brush and brush.sculpt_tool != 'MASK')
|
||||
if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
|
||||
@@ -806,7 +876,15 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
|
||||
if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
|
||||
col.operator("sculpt.detail_flood_fill")
|
||||
|
||||
col.prop(sculpt, "use_dyntopo_cleanup")
|
||||
col.prop(sculpt, "use_smooth_shading")
|
||||
col.prop(sculpt, "use_flat_vcol_shading")
|
||||
|
||||
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_spacing", slider=True)
|
||||
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_radius_scale", slider=True)
|
||||
|
||||
#col.prop(sculpt, "dyntopo_spacing")
|
||||
#col.prop(sculpt, "dyntopo_radius_scale");
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
|
||||
@@ -837,6 +915,7 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
|
||||
col.prop(mesh, "use_remesh_preserve_volume", text="Volume")
|
||||
col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask")
|
||||
col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets")
|
||||
col.prop(mesh, "use_remesh_preserve_materials", text="Materials")
|
||||
if context.preferences.experimental.use_sculpt_vertex_colors:
|
||||
col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors")
|
||||
|
||||
@@ -865,15 +944,36 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
|
||||
col = layout.column(heading="Display", align=True)
|
||||
col.prop(sculpt, "show_low_resolution")
|
||||
col.prop(sculpt, "use_sculpt_delay_updates")
|
||||
col.prop(sculpt, "use_fast_draw")
|
||||
col.prop(sculpt, "use_deform_only")
|
||||
col.prop(sculpt, "show_sculpt_pivot")
|
||||
col.prop(sculpt, "smooth_strength_factor")
|
||||
|
||||
col.separator()
|
||||
|
||||
brush = sculpt.brush
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout.column(),
|
||||
context,
|
||||
brush,
|
||||
"automasking", toolsettings_only=True)
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout.column(),
|
||||
context,
|
||||
brush,
|
||||
"automasking_boundary_edges_propagation_steps",
|
||||
toolsettings_only=True)
|
||||
|
||||
"""
|
||||
col = layout.column(heading="Auto-Masking", align=True)
|
||||
col.prop(sculpt, "use_automasking_topology", text="Topology")
|
||||
col.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
|
||||
col.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
|
||||
col.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
||||
"""
|
||||
|
||||
col.separator()
|
||||
col.operator("sculpt.set_limit_surface")
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel):
|
||||
@@ -938,6 +1038,7 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
|
||||
row.prop(sculpt, "tile_z", text="Z", toggle=True)
|
||||
|
||||
layout.prop(sculpt, "use_symmetry_feather", text="Feather")
|
||||
layout.prop(mesh, "use_fset_boundary_mirror")
|
||||
layout.prop(sculpt, "radial_symmetry", text="Radial")
|
||||
layout.prop(sculpt, "tile_offset", text="Tile Offset")
|
||||
|
||||
@@ -945,6 +1046,7 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
|
||||
|
||||
layout.prop(sculpt, "symmetrize_direction")
|
||||
layout.operator("sculpt.symmetrize")
|
||||
layout.prop(WindowManager.operator_properties_last("sculpt.symmetrize"), "merge_tolerance")
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel):
|
||||
@@ -2278,6 +2380,7 @@ classes = (
|
||||
VIEW3D_PT_tools_grease_pencil_brush_vertex_color,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_vertex_palette,
|
||||
VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff,
|
||||
VIEW3D_PT_sculpt_dyntopo_advanced
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
@@ -39,7 +39,7 @@ extern "C" {
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 22
|
||||
#define BLENDER_FILE_SUBVERSION 24
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
@@ -36,6 +36,8 @@ struct Main;
|
||||
struct Scene;
|
||||
struct ToolSettings;
|
||||
struct UnifiedPaintSettings;
|
||||
struct DynTopoSettings;
|
||||
struct Sculpt;
|
||||
|
||||
// enum eCurveMappingPreset;
|
||||
|
||||
@@ -108,8 +110,13 @@ const float *BKE_brush_color_get(const struct Scene *scene, const struct Brush *
|
||||
const float *BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush);
|
||||
void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]);
|
||||
|
||||
int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush);
|
||||
void BKE_brush_size_set(struct Scene *scene, struct Brush *brush, int size);
|
||||
int BKE_brush_size_get(const struct Scene *scene,
|
||||
const struct Brush *brush,
|
||||
bool use_brush_channel);
|
||||
void BKE_brush_size_set(struct Scene *scene,
|
||||
struct Brush *brush,
|
||||
int size,
|
||||
bool use_brush_channel);
|
||||
|
||||
float BKE_brush_unprojected_radius_get(const struct Scene *scene, const struct Brush *brush);
|
||||
void BKE_brush_unprojected_radius_set(struct Scene *scene,
|
||||
@@ -137,6 +144,8 @@ void BKE_brush_scale_size(int *r_brush_size,
|
||||
float new_unprojected_radius,
|
||||
float old_unprojected_radius);
|
||||
|
||||
void BKE_brush_default_input_curves_set(struct Brush *brush);
|
||||
|
||||
/* Accessors */
|
||||
#define BKE_brush_tool_get(brush, p) \
|
||||
(CHECK_TYPE_ANY(brush, struct Brush *, const struct Brush *), \
|
||||
@@ -151,6 +160,13 @@ void BKE_brush_scale_size(int *r_brush_size,
|
||||
/* debugging only */
|
||||
void BKE_brush_debug_print_state(struct Brush *br);
|
||||
|
||||
void BKE_brush_get_dyntopo(struct Brush *brush, struct Sculpt *sd, struct DynTopoSettings *out);
|
||||
|
||||
bool BKE_brush_hard_edge_mode_get(const struct Scene *scene, const struct Brush *brush);
|
||||
void BKE_brush_hard_edge_mode_set(struct Scene *scene, struct Brush *brush, bool val);
|
||||
|
||||
float BKE_brush_fset_slide_get(const struct Scene *scene, const struct Brush *brush);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
267
source/blender/blenkernel/BKE_brush_engine.h
Normal file
267
source/blender/blenkernel/BKE_brush_engine.h
Normal file
@@ -0,0 +1,267 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* 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 bke
|
||||
* \brief New brush engine for sculpt
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "RNA_types.h"
|
||||
|
||||
/*
|
||||
The new brush engine is based on command lists. These lists
|
||||
will eventually be created by a node editor.
|
||||
|
||||
Key is the concept of BrushChannels. A brush channel is
|
||||
a logical parameter with a type, input settings (e.g. pen),
|
||||
a falloff curve, etc.
|
||||
|
||||
Brush channels have a concept of inheritance. There is a
|
||||
BrushChannelSet (collection of channels) in Sculpt,
|
||||
in Brush, and in BrushCommand. Inheritence behavior
|
||||
is controller via BrushChannel->flag.
|
||||
|
||||
This should completely replace UnifiedPaintSettings.
|
||||
*/
|
||||
|
||||
#include "DNA_sculpt_brush_types.h"
|
||||
|
||||
struct BrushChannel;
|
||||
struct BlendWriter;
|
||||
struct BlendDataReader;
|
||||
struct Brush;
|
||||
struct Sculpt;
|
||||
|
||||
//#define DEBUG_CURVE_MAPPING_ALLOC
|
||||
#ifdef DEBUG_CURVE_MAPPING_ALLOC
|
||||
void namestack_push(const char *name);
|
||||
void *namestack_pop(void *passthru);
|
||||
#endif
|
||||
|
||||
typedef struct BrushMappingDef {
|
||||
int curve;
|
||||
bool enabled;
|
||||
bool inv;
|
||||
float min, max;
|
||||
int blendmode;
|
||||
float factor; // if 0, will default to 1.0
|
||||
} BrushMappingDef;
|
||||
|
||||
typedef struct BrushMappingPreset {
|
||||
// must match order of BRUSH_MAPPING_XXX enums
|
||||
struct BrushMappingDef pressure, xtilt, ytilt, angle, speed;
|
||||
} BrushMappingPreset;
|
||||
|
||||
typedef struct BrushMappingData {
|
||||
float pressure, xtilt, ytilt, angle, speed;
|
||||
} BrushMappingData;
|
||||
|
||||
#define MAX_BRUSH_ENUM_DEF 32
|
||||
|
||||
typedef struct BrushEnumDef {
|
||||
int value;
|
||||
const char identifier[64];
|
||||
char icon[32];
|
||||
const char name[64];
|
||||
const char description[512];
|
||||
} BrushEnumDef;
|
||||
|
||||
typedef struct BrushChannelType {
|
||||
char name[64], idname[64], tooltip[512];
|
||||
float min, max, soft_min, soft_max;
|
||||
BrushMappingPreset mappings;
|
||||
|
||||
int type, flag;
|
||||
int ivalue;
|
||||
float fvalue;
|
||||
float vector[4];
|
||||
|
||||
BrushEnumDef enumdef[MAX_BRUSH_ENUM_DEF]; // for enum/bitmask types
|
||||
EnumPropertyItem *rna_enumdef;
|
||||
|
||||
bool user_defined;
|
||||
} BrushChannelType;
|
||||
|
||||
typedef struct BrushCommand {
|
||||
int tool;
|
||||
float last_spacing_t[512]; // for different symmetry passes
|
||||
struct BrushChannelSet *params;
|
||||
struct BrushChannelSet *params_final;
|
||||
struct BrushChannelSet *params_mapped;
|
||||
} BrushCommand;
|
||||
|
||||
typedef struct BrushCommandList {
|
||||
BrushCommand *commands;
|
||||
int totcommand;
|
||||
} BrushCommandList;
|
||||
|
||||
void BKE_brush_channel_free_data(BrushChannel *ch);
|
||||
void BKE_brush_channel_free(BrushChannel *ch);
|
||||
void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src);
|
||||
void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def);
|
||||
|
||||
BrushChannelSet *BKE_brush_channelset_create();
|
||||
#ifdef DEBUG_CURVE_MAPPING_ALLOC
|
||||
BrushChannelSet *_BKE_brush_channelset_copy(BrushChannelSet *src);
|
||||
# define BKE_brush_channelset_copy(src) \
|
||||
(namestack_push(__func__), (BrushChannelSet *)namestack_pop(_BKE_brush_channelset_copy(src)))
|
||||
#else
|
||||
BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *src);
|
||||
#endif
|
||||
void BKE_brush_channelset_free(BrushChannelSet *chset);
|
||||
|
||||
void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch);
|
||||
|
||||
// makes a copy of ch
|
||||
void BKE_brush_channelset_add_duplicate(BrushChannelSet *chset, BrushChannel *ch);
|
||||
|
||||
// does not add to namemap ghash
|
||||
void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *ch);
|
||||
|
||||
// does not free ch or its data
|
||||
void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChannel *ch);
|
||||
|
||||
// does not free ch or its data
|
||||
bool BKE_brush_channelset_remove_named(BrushChannelSet *chset, const char *idname);
|
||||
|
||||
// checks is a channel with existing->idname exists; if not a copy of existing is made and inserted
|
||||
void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset, BrushChannel *existing);
|
||||
|
||||
BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname);
|
||||
|
||||
bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname);
|
||||
|
||||
void BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname);
|
||||
bool BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname);
|
||||
|
||||
void BKE_brush_channelset_merge(BrushChannelSet *dst,
|
||||
BrushChannelSet *child,
|
||||
BrushChannelSet *parent);
|
||||
|
||||
void BKE_brush_resolve_channels(struct Brush *brush, struct Sculpt *sd);
|
||||
|
||||
void BKE_brush_channelset_set_final_int(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
const char *idname,
|
||||
int value);
|
||||
|
||||
int BKE_brush_channelset_get_final_int(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata);
|
||||
|
||||
int BKE_brush_channelset_get_int(BrushChannelSet *chset,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata);
|
||||
bool BKE_brush_channelset_set_int(BrushChannelSet *chset, const char *idname, int val);
|
||||
|
||||
void BKE_brush_channel_set_int(BrushChannel *ch, int val);
|
||||
float BKE_brush_channel_get_int(BrushChannel *ch, BrushMappingData *mapdata);
|
||||
|
||||
// mapdata is optional, can be NULL
|
||||
|
||||
/* mapdata may be NULL */
|
||||
float BKE_brush_channel_get_float(BrushChannel *ch, BrushMappingData *mapdata);
|
||||
void BKE_brush_channel_set_float(BrushChannel *ch, float val);
|
||||
|
||||
/* mapdata may be NULL */
|
||||
float BKE_brush_channelset_get_float(BrushChannelSet *chset,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata);
|
||||
bool BKE_brush_channelset_set_float(BrushChannelSet *chset, const char *idname, float val);
|
||||
|
||||
float BKE_brush_channelset_get_final_float(BrushChannelSet *child,
|
||||
BrushChannelSet *parent,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata);
|
||||
|
||||
void BKE_brush_channelset_set_final_float(BrushChannelSet *child,
|
||||
BrushChannelSet *parent,
|
||||
const char *idname,
|
||||
float value);
|
||||
|
||||
void BKE_brush_channel_set_vector(BrushChannel *ch, float vec[4]);
|
||||
int BKE_brush_channel_get_vector_size(BrushChannel *ch);
|
||||
|
||||
/* returns size of vector */
|
||||
int BKE_brush_channel_get_vector(BrushChannel *ch, float out[4], BrushMappingData *mapdata);
|
||||
|
||||
float BKE_brush_channelset_get_final_vector(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
const char *idname,
|
||||
float r_vec[4],
|
||||
BrushMappingData *mapdata);
|
||||
void BKE_brush_channelset_set_final_vector(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
const char *idname,
|
||||
float vec[4]);
|
||||
int BKE_brush_channelset_get_vector(BrushChannelSet *chset,
|
||||
const char *idname,
|
||||
float r_vec[4],
|
||||
BrushMappingData *mapdata);
|
||||
bool BKE_brush_channelset_set_vector(BrushChannelSet *chset, const char *idname, float vec[4]);
|
||||
|
||||
void BKE_brush_init_toolsettings(struct Sculpt *sd);
|
||||
void BKE_brush_builtin_create(struct Brush *brush, int tool);
|
||||
BrushCommandList *BKE_brush_commandlist_create();
|
||||
void BKE_brush_commandlist_free(BrushCommandList *cl);
|
||||
BrushCommand *BKE_brush_commandlist_add(BrushCommandList *cl,
|
||||
BrushChannelSet *chset_template,
|
||||
bool auto_inherit);
|
||||
BrushCommand *BKE_brush_command_init(BrushCommand *command, int tool);
|
||||
void BKE_builtin_commandlist_create(struct Brush *brush,
|
||||
BrushChannelSet *chset,
|
||||
BrushCommandList *cl,
|
||||
int tool,
|
||||
BrushMappingData *map_data); // map_data may be NULL
|
||||
void BKE_brush_channelset_read(struct BlendDataReader *reader, BrushChannelSet *cset);
|
||||
void BKE_brush_channelset_write(struct BlendWriter *writer, BrushChannelSet *cset);
|
||||
void BKE_brush_mapping_copy_data(BrushMapping *dst, BrushMapping *src);
|
||||
const char *BKE_brush_mapping_type_to_str(BrushMappingType mapping);
|
||||
const char *BKE_brush_mapping_type_to_typename(BrushMappingType mapping);
|
||||
|
||||
void BKE_brush_channelset_flag_clear(BrushChannelSet *chset, const char *channel, int flag);
|
||||
void BKE_brush_channelset_flag_set(BrushChannelSet *chset, const char *channel, int flag);
|
||||
|
||||
/* adds missing channels to exising .channels in brush.
|
||||
* if channels do not exist use BKE_brush_builtin_create.
|
||||
*/
|
||||
void BKE_brush_builtin_patch(struct Brush *brush, int tool);
|
||||
|
||||
void BKE_brush_channelset_compat_load(BrushChannelSet *chset,
|
||||
struct Brush *brush,
|
||||
bool to_channels);
|
||||
|
||||
// merge in channels the ui requested
|
||||
void BKE_brush_apply_queued_channels(BrushChannelSet *chset, bool do_override);
|
||||
void BKE_brush_channeltype_rna_check(BrushChannelType *def,
|
||||
int (*getIconFromName)(const char *name));
|
||||
bool BKE_brush_mapping_ensure_write(BrushMapping *mp);
|
||||
|
||||
void BKE_brush_channelset_apply_mapping(BrushChannelSet *chset, BrushMappingData *mapdata);
|
||||
void BKE_brush_check_toolsettings(struct Sculpt *sd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
26
source/blender/blenkernel/BKE_curvemapping_cache.h
Normal file
26
source/blender/blenkernel/BKE_curvemapping_cache.h
Normal file
@@ -0,0 +1,26 @@
|
||||
struct GHash;
|
||||
struct CurveMapping;
|
||||
|
||||
typedef struct CurveMappingCache {
|
||||
struct GHash *gh;
|
||||
} CurveMappingCache;
|
||||
|
||||
bool BKE_curvemapping_equals(const struct CurveMapping *a, const struct CurveMapping *b);
|
||||
uint BKE_curvemapping_calc_hash(const struct CurveMapping *cumap);
|
||||
|
||||
CurveMappingCache *BKE_curvemapping_cache_create(void);
|
||||
CurveMapping *BKE_curvemapping_cache_get(CurveMappingCache *cache,
|
||||
CurveMapping *curve,
|
||||
bool free_input);
|
||||
void BKE_curvemapping_cache_free(CurveMappingCache *cache);
|
||||
|
||||
CurveMappingCache *BKE_curvemapping_cache_global(void);
|
||||
|
||||
// takes a curve that's already in the cache and increases its user count
|
||||
void BKE_curvemapping_cache_aquire(CurveMappingCache *cache, CurveMapping *curve);
|
||||
void BKE_curvemapping_cache_release(CurveMappingCache *cache, CurveMapping *curve);
|
||||
|
||||
bool BKE_curvemapping_in_cache(CurveMapping *curve);
|
||||
void BKE_curvemapping_cache_release_or_free(CurveMappingCache *cache, CurveMapping *curve);
|
||||
|
||||
void BKE_curvemapping_cache_exit();
|
@@ -105,6 +105,8 @@ bool CustomData_has_math(const struct CustomData *data);
|
||||
bool CustomData_has_interp(const struct CustomData *data);
|
||||
bool CustomData_bmesh_has_free(const struct CustomData *data);
|
||||
|
||||
bool CustomData_layout_is_same(const struct CustomData *_a, const struct CustomData *_b);
|
||||
|
||||
/**
|
||||
* Checks if any of the customdata layers is referenced.
|
||||
*/
|
||||
@@ -141,6 +143,10 @@ void CustomData_copy(const struct CustomData *source,
|
||||
/* BMESH_TODO, not really a public function but readfile.c needs it */
|
||||
void CustomData_update_typemap(struct CustomData *data);
|
||||
|
||||
/* copies all customdata layers without allocating data,
|
||||
* and without respect to type masks or NO_COPY/etc flags*/
|
||||
void CustomData_copy_all_layout(const struct CustomData *source, struct CustomData *dest);
|
||||
|
||||
/* same as the above, except that this will preserve existing layers, and only
|
||||
* add the layers that were not there yet */
|
||||
bool CustomData_merge(const struct CustomData *source,
|
||||
@@ -277,6 +283,16 @@ void CustomData_copy_data_named(const struct CustomData *source,
|
||||
int dest_index,
|
||||
int count);
|
||||
void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs, int count);
|
||||
|
||||
// ignores CD_MESH_ID layer if it exists
|
||||
void CustomData_bmesh_swap_data(struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
void *src_block,
|
||||
void **dest_block);
|
||||
|
||||
// simple pointer swap; will unswaps ids if a CD_MESH_ID layer exists
|
||||
void CustomData_bmesh_swap_data_simple(CustomData *data, void **block1, void **block2);
|
||||
|
||||
void CustomData_bmesh_copy_data(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
void *src_block,
|
||||
@@ -605,6 +621,11 @@ void CustomData_blend_write(struct BlendWriter *writer,
|
||||
struct ID *id);
|
||||
void CustomData_blend_read(struct BlendDataReader *reader, struct CustomData *data, int count);
|
||||
|
||||
void CustomData_unmark_temporary_nocopy(struct CustomData *data);
|
||||
void CustomData_mark_temporary_nocopy(struct CustomData *data);
|
||||
|
||||
int CustomData_get_elem_size(CustomDataLayer *layer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -54,9 +54,11 @@ enum {
|
||||
DT_TYPE_UV = 1 << 24,
|
||||
DT_TYPE_SHARP_FACE = 1 << 25,
|
||||
DT_TYPE_FREESTYLE_FACE = 1 << 26,
|
||||
#define DT_TYPE_MAX 27
|
||||
DT_TYPE_PROPCOL = 1 << 27,
|
||||
#define DT_TYPE_MAX 28
|
||||
|
||||
DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT,
|
||||
DT_TYPE_VERT_ALL = DT_TYPE_MDEFORMVERT | DT_TYPE_SHAPEKEY | DT_TYPE_SKIN | DT_TYPE_BWEIGHT_VERT |
|
||||
DT_TYPE_PROPCOL,
|
||||
DT_TYPE_EDGE_ALL = DT_TYPE_SHARP_EDGE | DT_TYPE_SEAM | DT_TYPE_CREASE | DT_TYPE_BWEIGHT_EDGE |
|
||||
DT_TYPE_FREESTYLE_EDGE,
|
||||
DT_TYPE_LOOP_ALL = DT_TYPE_VCOL | DT_TYPE_LNOR | DT_TYPE_UV,
|
||||
@@ -74,7 +76,7 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type);
|
||||
int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type);
|
||||
|
||||
#define DT_DATATYPE_IS_VERT(_dt) \
|
||||
ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_SKIN, DT_TYPE_BWEIGHT_VERT)
|
||||
ELEM(_dt, DT_TYPE_MDEFORMVERT, DT_TYPE_SHAPEKEY, DT_TYPE_SKIN, DT_TYPE_BWEIGHT_VERT, DT_TYPE_PROPCOL)
|
||||
#define DT_DATATYPE_IS_EDGE(_dt) \
|
||||
ELEM(_dt, \
|
||||
DT_TYPE_CREASE, \
|
||||
@@ -94,7 +96,8 @@ enum {
|
||||
DT_MULTILAYER_INDEX_SHAPEKEY = 1,
|
||||
DT_MULTILAYER_INDEX_VCOL = 2,
|
||||
DT_MULTILAYER_INDEX_UV = 3,
|
||||
DT_MULTILAYER_INDEX_MAX = 4,
|
||||
DT_MULTILAYER_INDEX_PROPCOL = 4,
|
||||
DT_MULTILAYER_INDEX_MAX = 5,
|
||||
};
|
||||
|
||||
/* Below we keep positive values for real layers idx (generated dynamically). */
|
||||
|
24
source/blender/blenkernel/BKE_dyntopo.h
Normal file
24
source/blender/blenkernel/BKE_dyntopo.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* \brief Dynamic topology remeshing API
|
||||
*/
|
||||
|
||||
typedef struct DynTopo DynTopo;
|
@@ -78,8 +78,12 @@ typedef struct FModifierTypeInfo {
|
||||
short size;
|
||||
/** #eFMI_Action_Types. */
|
||||
short acttype;
|
||||
#ifdef __cplusplus
|
||||
short requires_;
|
||||
#else
|
||||
/** #eFMI_Requirement_Flags. */
|
||||
short requires;
|
||||
#endif
|
||||
/** name of modifier in interface. */
|
||||
char name[64];
|
||||
/** name of struct for SDNA. */
|
||||
|
@@ -69,7 +69,8 @@ extern "C" {
|
||||
|
||||
/* *** mesh.c *** */
|
||||
|
||||
struct BMesh *BKE_mesh_to_bmesh_ex(const struct Mesh *me,
|
||||
struct BMesh *BKE_mesh_to_bmesh_ex(const struct Object *ob,
|
||||
const struct Mesh *me,
|
||||
const struct BMeshCreateParams *create_params,
|
||||
const struct BMeshFromMeshParams *convert_params);
|
||||
struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me,
|
||||
@@ -636,7 +637,7 @@ void BKE_mesh_calc_edges_tessface(struct Mesh *mesh);
|
||||
|
||||
/* In DerivedMesh.cc */
|
||||
void BKE_mesh_wrapper_deferred_finalize(struct Mesh *me_eval,
|
||||
const CustomData_MeshMasks *cd_mask_finalize);
|
||||
const struct CustomData_MeshMasks *cd_mask_finalize);
|
||||
|
||||
/* **** Depsgraph evaluation **** */
|
||||
|
||||
|
@@ -36,6 +36,7 @@ extern "C" {
|
||||
typedef enum eMeshFairingDepth {
|
||||
MESH_FAIRING_DEPTH_POSITION = 1,
|
||||
MESH_FAIRING_DEPTH_TANGENCY = 2,
|
||||
MESH_FAIRING_DEPTH_CURVATURE = 3,
|
||||
} eMeshFairingDepth;
|
||||
|
||||
/* affect_vertices is used to define the fairing area. Indexed by vertex index, set to true when
|
||||
|
@@ -105,20 +105,28 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly,
|
||||
UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v);
|
||||
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap);
|
||||
|
||||
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const struct MPoly *mpoly,
|
||||
const struct MLoop *mloop,
|
||||
int totvert,
|
||||
int totpoly,
|
||||
int totloop);
|
||||
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const struct MPoly *mpoly,
|
||||
const struct MLoop *mloop,
|
||||
int totvert,
|
||||
int totpoly,
|
||||
int totloop);
|
||||
void BKE_mesh_vert_poly_map_create(
|
||||
MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const struct MVert *mvert, // only needed if sort_disk_cycles is true
|
||||
const struct MEdge *medge, // only needed if sort_disk_cycles is true
|
||||
const struct MPoly *mpoly,
|
||||
const struct MLoop *mloop,
|
||||
int totvert,
|
||||
int totpoly,
|
||||
int totloop,
|
||||
const bool sort_disk_cycles); // put polys in sorted geometric order
|
||||
void BKE_mesh_vert_loop_map_create(
|
||||
MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const struct MVert *mvert, // only needed if sort_disk_cycles is true
|
||||
const struct MEdge *medge, // only needed if sort_disk_cycles is true
|
||||
const struct MPoly *mpoly,
|
||||
const struct MLoop *mloop,
|
||||
int totvert,
|
||||
int totpoly,
|
||||
int totloop,
|
||||
const bool sort_disk_cycles); // put loops in sorted geometric order
|
||||
void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const struct MVert *mvert,
|
||||
@@ -128,7 +136,13 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
|
||||
const struct MLoop *mloop,
|
||||
const int totloop);
|
||||
void BKE_mesh_vert_edge_map_create(
|
||||
MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, int totvert, int totedge);
|
||||
MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const struct MVert *mvert, // only needed if sort_disk_cycles is true
|
||||
const struct MEdge *medge,
|
||||
int totvert,
|
||||
int totedge,
|
||||
bool sort_disk_cycles); // sort verts in geometric order around edges
|
||||
void BKE_mesh_vert_edge_vert_map_create(
|
||||
MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, int totvert, int totedge);
|
||||
void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map,
|
||||
|
@@ -32,7 +32,7 @@ struct Mesh;
|
||||
struct MirrorModifierData;
|
||||
struct Object;
|
||||
|
||||
struct Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(struct MirrorModifierData *mmd,
|
||||
struct Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(struct Object *ob, struct MirrorModifierData *mmd,
|
||||
const struct Mesh *mesh,
|
||||
int axis,
|
||||
const float plane_co[3],
|
||||
|
@@ -47,6 +47,8 @@ struct Mesh *BKE_mesh_remesh_quadriflow(const struct Mesh *mesh,
|
||||
void BKE_mesh_remesh_reproject_paint_mask(struct Mesh *target, struct Mesh *source);
|
||||
void BKE_remesh_reproject_vertex_paint(struct Mesh *target, const struct Mesh *source);
|
||||
void BKE_remesh_reproject_sculpt_face_sets(struct Mesh *target, struct Mesh *source);
|
||||
void BKE_remesh_reproject_materials(struct Mesh *target, struct Mesh *source);
|
||||
void BKE_mesh_remesh_sculpt_array_update(struct Object *ob, struct Mesh *target, struct Mesh *source);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -39,6 +39,7 @@ struct MultiresModifierData;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct SubdivCCG;
|
||||
struct BMesh;
|
||||
|
||||
struct MLoop;
|
||||
struct MLoopTri;
|
||||
@@ -217,6 +218,7 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3]
|
||||
const float dPdv[3],
|
||||
const int corner);
|
||||
|
||||
void BKE_multires_bmesh_space_set(struct Object *ob, struct BMesh *bm, int mode);
|
||||
/* Versioning. */
|
||||
|
||||
/* Convert displacement which is stored for simply-subdivided mesh to a Catmull-Clark
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#include "DNA_object_enums.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
#include "BKE_lib_id.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -154,8 +156,8 @@ bool BKE_object_obdata_is_libdata(const struct Object *ob);
|
||||
|
||||
struct Object *BKE_object_duplicate(struct Main *bmain,
|
||||
struct Object *ob,
|
||||
uint dupflag,
|
||||
const uint duplicate_options);
|
||||
eDupli_ID_Flags dupflag,
|
||||
const eLibIDDuplicateFlags duplicate_options);
|
||||
|
||||
void BKE_object_obdata_size_init(struct Object *ob, const float size);
|
||||
|
||||
|
@@ -23,15 +23,21 @@
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BKE_brush_engine.h"
|
||||
#include "BKE_pbvh.h"
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "DNA_brush_enums.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_object_enums.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct SculptCustomLayer;
|
||||
struct MDynTopoVert;
|
||||
struct BMFace;
|
||||
struct BMesh;
|
||||
struct BlendDataReader;
|
||||
@@ -260,6 +266,11 @@ typedef struct SculptPoseIKChain {
|
||||
SculptPoseIKChainSegment *segments;
|
||||
int tot_segments;
|
||||
float grab_delta_offset[3];
|
||||
float bend_mat[4][4];
|
||||
float bend_mat_inv[4][4];
|
||||
float bend_factor;
|
||||
float bend_limit;
|
||||
float bend_upper_limit;
|
||||
} SculptPoseIKChain;
|
||||
|
||||
/* Cloth Brush */
|
||||
@@ -335,6 +346,7 @@ typedef struct SculptClothSimulation {
|
||||
float (*softbody_pos)[3];
|
||||
float (*prev_pos)[3];
|
||||
float (*last_iteration_pos)[3];
|
||||
float (*init_normal)[3];
|
||||
|
||||
struct ListBase *collider_list;
|
||||
|
||||
@@ -342,6 +354,11 @@ typedef struct SculptClothSimulation {
|
||||
/** #PBVHNode pointer as a key, index in #SculptClothSimulation.node_state as value. */
|
||||
struct GHash *node_state_index;
|
||||
eSculptClothNodeSimState *node_state;
|
||||
|
||||
// persistent base customdata layer offsets
|
||||
int cd_pers_co;
|
||||
int cd_pers_no;
|
||||
int cd_pers_disp;
|
||||
} SculptClothSimulation;
|
||||
|
||||
typedef struct SculptPersistentBase {
|
||||
@@ -356,11 +373,15 @@ typedef struct SculptVertexInfo {
|
||||
|
||||
/* Indexed by base mesh vertex index, stores if that vertex is a boundary. */
|
||||
BLI_bitmap *boundary;
|
||||
|
||||
/* Indexed by vertex, stores the symmetrical topology vertex index found by symmetrize. */
|
||||
int *symmetrize_map;
|
||||
} SculptVertexInfo;
|
||||
|
||||
typedef struct SculptBoundaryEditInfo {
|
||||
/* Vertex index from where the topology propagation reached this vertex. */
|
||||
int original_vertex;
|
||||
SculptVertRef original_vertex;
|
||||
int original_vertex_i;
|
||||
|
||||
/* How many steps were needed to reach this vertex from the boundary. */
|
||||
int num_propagation_steps;
|
||||
@@ -371,13 +392,23 @@ typedef struct SculptBoundaryEditInfo {
|
||||
|
||||
/* Edge for drawing the boundary preview in the cursor. */
|
||||
typedef struct SculptBoundaryPreviewEdge {
|
||||
int v1;
|
||||
int v2;
|
||||
SculptVertRef v1;
|
||||
SculptVertRef v2;
|
||||
} SculptBoundaryPreviewEdge;
|
||||
|
||||
#define MAX_STORED_COTANGENTW_EDGES 7
|
||||
|
||||
typedef struct StoredCotangentW {
|
||||
float static_weights[MAX_STORED_COTANGENTW_EDGES];
|
||||
float *weights;
|
||||
int length;
|
||||
} StoredCotangentW;
|
||||
|
||||
typedef struct SculptBoundary {
|
||||
/* Vertex indices of the active boundary. */
|
||||
int *vertices;
|
||||
SculptVertRef *vertices;
|
||||
int *vertex_indices;
|
||||
|
||||
int vertices_capacity;
|
||||
int num_vertices;
|
||||
|
||||
@@ -386,6 +417,14 @@ typedef struct SculptBoundary {
|
||||
* a distance of 0. */
|
||||
float *distance;
|
||||
|
||||
float (*smoothco)[3];
|
||||
float *boundary_dist; // distances from verts to boundary
|
||||
float (*boundary_tangents)[3];
|
||||
|
||||
StoredCotangentW *boundary_cotangents;
|
||||
SculptVertRef *boundary_closest;
|
||||
int sculpt_totvert;
|
||||
|
||||
/* Data for drawing the preview. */
|
||||
SculptBoundaryPreviewEdge *edges;
|
||||
int edges_capacity;
|
||||
@@ -395,12 +434,12 @@ typedef struct SculptBoundary {
|
||||
bool forms_loop;
|
||||
|
||||
/* Initial vertex in the boundary which is closest to the current sculpt active vertex. */
|
||||
int initial_vertex;
|
||||
SculptVertRef initial_vertex;
|
||||
|
||||
/* Vertex that at max_propagation_steps from the boundary and closest to the original active
|
||||
* vertex that was used to initialize the boundary. This is used as a reference to check how much
|
||||
* the deformation will go into the mesh and to calculate the strength of the brushes. */
|
||||
int pivot_vertex;
|
||||
SculptVertRef pivot_vertex;
|
||||
|
||||
/* Stores the initial positions of the pivot and boundary initial vertex as they may be deformed
|
||||
* during the brush action. This allows to use them as a reference positions and vectors for some
|
||||
@@ -418,7 +457,7 @@ typedef struct SculptBoundary {
|
||||
/* Bend Deform type. */
|
||||
struct {
|
||||
float (*pivot_rotation_axis)[3];
|
||||
float (*pivot_positions)[3];
|
||||
float (*pivot_positions)[4];
|
||||
} bend;
|
||||
|
||||
/* Slide Deform type. */
|
||||
@@ -431,8 +470,61 @@ typedef struct SculptBoundary {
|
||||
float rotation_axis[3];
|
||||
float pivot_position[3];
|
||||
} twist;
|
||||
|
||||
/* Cicrle Deform type. */
|
||||
struct {
|
||||
float (*origin)[3];
|
||||
float *radius;
|
||||
} circle;
|
||||
} SculptBoundary;
|
||||
|
||||
/* Array Brush. */
|
||||
typedef struct SculptArrayCopy {
|
||||
int index;
|
||||
int symm_pass;
|
||||
float mat[4][4];
|
||||
float imat[4][4];
|
||||
float origin[3];
|
||||
} SculptArrayCopy;
|
||||
|
||||
typedef struct ScultpArrayPathPoint {
|
||||
float length;
|
||||
float strength;
|
||||
float co[3];
|
||||
float orco[3];
|
||||
float direction[3];
|
||||
} ScultpArrayPathPoint;
|
||||
|
||||
typedef struct SculptArray {
|
||||
SculptArrayCopy *copies[PAINT_SYMM_AREAS];
|
||||
int num_copies;
|
||||
|
||||
struct {
|
||||
ScultpArrayPathPoint *points;
|
||||
int tot_points;
|
||||
int capacity;
|
||||
float total_length;
|
||||
} path;
|
||||
|
||||
int mode;
|
||||
float normal[3];
|
||||
float direction[3];
|
||||
float radial_angle;
|
||||
float initial_radial_angle;
|
||||
|
||||
bool source_mat_valid;
|
||||
float source_origin[3];
|
||||
float source_mat[4][4];
|
||||
float source_imat[4][4];
|
||||
float (*orco)[3];
|
||||
|
||||
int *copy_index;
|
||||
int *symmetry_pass;
|
||||
|
||||
float *smooth_strength;
|
||||
|
||||
} SculptArray;
|
||||
|
||||
typedef struct SculptFakeNeighbors {
|
||||
bool use_fake_neighbors;
|
||||
|
||||
@@ -440,7 +532,7 @@ typedef struct SculptFakeNeighbors {
|
||||
float current_max_distance;
|
||||
|
||||
/* Indexed by vertex, stores the vertex index of its fake neighbor if available. */
|
||||
int *fake_neighbor_index;
|
||||
SculptVertRef *fake_neighbor_index;
|
||||
|
||||
} SculptFakeNeighbors;
|
||||
|
||||
@@ -459,8 +551,15 @@ typedef struct SculptSession {
|
||||
|
||||
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
|
||||
struct MVert *mvert;
|
||||
struct MPoly *mpoly;
|
||||
struct MEdge *medge;
|
||||
struct MLoop *mloop;
|
||||
struct MPoly *mpoly;
|
||||
|
||||
// only assigned in PBVH_FACES and PBVH_GRIDS
|
||||
CustomData *vdata, *edata, *ldata, *pdata;
|
||||
|
||||
// for grids
|
||||
CustomData temp_vdata, temp_pdata;
|
||||
|
||||
/* These contain the vertex and poly counts of the final mesh. */
|
||||
int totvert, totpoly;
|
||||
@@ -495,8 +594,13 @@ typedef struct SculptSession {
|
||||
|
||||
/* BMesh for dynamic topology sculpting */
|
||||
struct BMesh *bm;
|
||||
int cd_dyn_vert;
|
||||
int cd_vert_node_offset;
|
||||
int cd_face_node_offset;
|
||||
int cd_vcol_offset;
|
||||
int cd_faceset_offset;
|
||||
int cd_face_areas;
|
||||
|
||||
bool bm_smooth_shading;
|
||||
/* Undo/redo log for dynamic topology sculpting */
|
||||
struct BMLog *bm_log;
|
||||
@@ -509,6 +613,10 @@ typedef struct SculptSession {
|
||||
bool show_mask;
|
||||
bool show_face_sets;
|
||||
|
||||
/* Setting this to true allows a PBVH rebuild when evaluating the object even if the stroke or
|
||||
* filter caches are active. */
|
||||
bool needs_pbvh_rebuild;
|
||||
|
||||
/* Painting on deformed mesh */
|
||||
bool deform_modifiers_active; /* Object is deformed with some modifiers. */
|
||||
float (*orig_cos)[3]; /* Coords of un-deformed mesh. */
|
||||
@@ -524,9 +632,9 @@ typedef struct SculptSession {
|
||||
struct ExpandCache *expand_cache;
|
||||
|
||||
/* Cursor data and active vertex for tools */
|
||||
int active_vertex_index;
|
||||
SculptVertRef active_vertex_index;
|
||||
SculptFaceRef active_face_index;
|
||||
|
||||
int active_face_index;
|
||||
int active_grid_index;
|
||||
|
||||
/* When active, the cursor draws with faded colors, indicating that there is an action enabled.
|
||||
@@ -540,6 +648,7 @@ typedef struct SculptSession {
|
||||
|
||||
/* For Sculpt trimming gesture tools, initial raycast data from the position of the mouse when
|
||||
* the gesture starts (intersection with the surface and if they ray hit the surface or not). */
|
||||
float gesture_initial_back_location[3];
|
||||
float gesture_initial_location[3];
|
||||
float gesture_initial_normal[3];
|
||||
bool gesture_initial_hit;
|
||||
@@ -548,9 +657,17 @@ typedef struct SculptSession {
|
||||
struct RegionView3D *rv3d;
|
||||
struct View3D *v3d;
|
||||
struct Scene *scene;
|
||||
int cd_origvcol_offset;
|
||||
int cd_origco_offset;
|
||||
int cd_origno_offset;
|
||||
|
||||
/* Face Sets by topology. */
|
||||
int face_set_last_created;
|
||||
SculptFaceRef face_set_last_poly;
|
||||
SculptEdgeRef face_set_last_edge;
|
||||
|
||||
/* Dynamic mesh preview */
|
||||
int *preview_vert_index_list;
|
||||
SculptVertRef *preview_vert_index_list;
|
||||
int preview_vert_index_count;
|
||||
|
||||
/* Pose Brush Preview */
|
||||
@@ -564,9 +681,15 @@ typedef struct SculptSession {
|
||||
/* This is freed with the PBVH, so it is always in sync with the mesh. */
|
||||
SculptPersistentBase *persistent_base;
|
||||
|
||||
// float (*limit_surface)[3];
|
||||
struct SculptCustomLayer *limit_surface;
|
||||
|
||||
SculptVertexInfo vertex_info;
|
||||
SculptFakeNeighbors fake_neighbors;
|
||||
|
||||
/* Array. */
|
||||
SculptArray *array;
|
||||
|
||||
/* Transform operator */
|
||||
float pivot_pos[3];
|
||||
float pivot_rot[4];
|
||||
@@ -612,6 +735,13 @@ typedef struct SculptSession {
|
||||
*/
|
||||
char needs_flush_to_id;
|
||||
|
||||
// id of current stroke, used to detect
|
||||
// if vertex original data needs to be updated
|
||||
int stroke_id, boundary_symmetry;
|
||||
|
||||
bool fast_draw; // hides facesets/masks and forces smooth to save GPU bandwidth
|
||||
struct MDynTopoVert *mdyntopo_verts; // for non-bmesh
|
||||
int mdyntopo_verts_size;
|
||||
} SculptSession;
|
||||
|
||||
void BKE_sculptsession_free(struct Object *ob);
|
||||
@@ -619,6 +749,7 @@ void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
|
||||
void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
|
||||
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
|
||||
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
|
||||
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert);
|
||||
|
||||
/* Create new color layer on object if it doesn't have one and if experimental feature set has
|
||||
* sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise. */
|
||||
@@ -655,6 +786,8 @@ void BKE_sculpt_ensure_orig_mesh_data(struct Scene *scene, struct Object *object
|
||||
|
||||
bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d);
|
||||
|
||||
char BKE_get_fset_boundary_symflag(struct Object *object);
|
||||
|
||||
enum {
|
||||
SCULPT_MASK_LAYER_CALC_VERT = (1 << 0),
|
||||
SCULPT_MASK_LAYER_CALC_LOOP = (1 << 1),
|
||||
|
@@ -22,25 +22,103 @@
|
||||
*/
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_ghash.h"
|
||||
|
||||
/* For embedding CCGKey in iterator. */
|
||||
#include "BKE_ccg.h"
|
||||
#include <stdint.h>
|
||||
|
||||
//#define DEFRAGMENT_MEMORY
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// experimental feature to detect quad diagonals and mark (but not dissolve) them
|
||||
//#define SCULPT_DIAGONAL_EDGE_MARKS
|
||||
|
||||
typedef struct SculptVertRef {
|
||||
intptr_t i;
|
||||
} SculptVertRef;
|
||||
|
||||
typedef struct SculptEdgeRef {
|
||||
intptr_t i;
|
||||
} SculptEdgeRef;
|
||||
|
||||
typedef struct SculptFaceRef {
|
||||
intptr_t i;
|
||||
} SculptFaceRef;
|
||||
|
||||
#define SCULPT_REF_NONE ((intptr_t)-1)
|
||||
|
||||
#if 0
|
||||
typedef struct SculptLoopRef {
|
||||
intptr_t i;
|
||||
} SculptLoopRef;
|
||||
#endif
|
||||
|
||||
BLI_INLINE SculptVertRef BKE_pbvh_make_vref(intptr_t i)
|
||||
{
|
||||
SculptVertRef ret = {i};
|
||||
return ret;
|
||||
}
|
||||
|
||||
BLI_INLINE SculptEdgeRef BKE_pbvh_make_eref(intptr_t i)
|
||||
{
|
||||
SculptEdgeRef ret = {i};
|
||||
return ret;
|
||||
}
|
||||
|
||||
BLI_INLINE SculptFaceRef BKE_pbvh_make_fref(intptr_t i)
|
||||
{
|
||||
SculptFaceRef ret = {i};
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DEFRAGMENT_MEMORY
|
||||
# include "BLI_smallhash.h"
|
||||
#endif
|
||||
|
||||
typedef struct PBVHTri {
|
||||
int v[3]; // references into PBVHTriBuf->verts
|
||||
intptr_t l[3]; // loops
|
||||
int eflag; // bitmask of which edges in the tri are real edges in the mesh
|
||||
|
||||
float no[3];
|
||||
SculptFaceRef f;
|
||||
} PBVHTri;
|
||||
|
||||
typedef struct PBVHTriBuf {
|
||||
PBVHTri *tris;
|
||||
SculptVertRef *verts;
|
||||
int *edges;
|
||||
int totvert, totedge, tottri;
|
||||
int verts_size, edges_size, tris_size;
|
||||
|
||||
SmallHash vertmap; // maps vertex ptrs to indices within verts
|
||||
|
||||
// private field
|
||||
intptr_t *loops;
|
||||
int totloop, mat_nr;
|
||||
float min[3], max[3];
|
||||
} PBVHTriBuf;
|
||||
|
||||
struct BMLog;
|
||||
struct BMesh;
|
||||
struct BMVert;
|
||||
struct BMEdge;
|
||||
struct BMFace;
|
||||
struct CCGElem;
|
||||
struct CCGKey;
|
||||
struct CustomData;
|
||||
struct TableGSet;
|
||||
struct DMFlagMat;
|
||||
struct GPU_PBVH_Buffers;
|
||||
struct IsectRayPrecalc;
|
||||
struct MLoop;
|
||||
struct MLoopTri;
|
||||
struct MDynTopoVert;
|
||||
struct MPoly;
|
||||
struct MVert;
|
||||
struct Mesh;
|
||||
@@ -52,12 +130,86 @@ struct TaskParallelSettings;
|
||||
typedef struct PBVH PBVH;
|
||||
typedef struct PBVHNode PBVHNode;
|
||||
|
||||
//#define PROXY_ADVANCED
|
||||
|
||||
// experimental performance test of "data-based programming" approach
|
||||
#ifdef PROXY_ADVANCED
|
||||
typedef struct ProxyKey {
|
||||
int node;
|
||||
int pindex;
|
||||
} ProxyKey;
|
||||
|
||||
# define MAX_PROXY_NEIGHBORS 12
|
||||
|
||||
typedef struct ProxyVertArray {
|
||||
float **ownerco;
|
||||
short **ownerno;
|
||||
float (*co)[3];
|
||||
float (*fno)[3];
|
||||
short (*no)[3];
|
||||
float *mask, **ownermask;
|
||||
SculptVertRef *index;
|
||||
float **ownercolor, (*color)[4];
|
||||
|
||||
ProxyKey (*neighbors)[MAX_PROXY_NEIGHBORS];
|
||||
|
||||
int size;
|
||||
int datamask;
|
||||
bool neighbors_dirty;
|
||||
|
||||
GHash *indexmap;
|
||||
} ProxyVertArray;
|
||||
|
||||
typedef enum {
|
||||
PV_OWNERCO = 1,
|
||||
PV_OWNERNO = 2,
|
||||
PV_CO = 4,
|
||||
PV_NO = 8,
|
||||
PV_MASK = 16,
|
||||
PV_OWNERMASK = 32,
|
||||
PV_INDEX = 64,
|
||||
PV_OWNERCOLOR = 128,
|
||||
PV_COLOR = 256,
|
||||
PV_NEIGHBORS = 512
|
||||
} ProxyVertField;
|
||||
|
||||
typedef struct ProxyVertUpdateRec {
|
||||
float *co, *no, *mask, *color;
|
||||
SculptVertRef index, newindex;
|
||||
} ProxyVertUpdateRec;
|
||||
|
||||
# define PBVH_PROXY_DEFAULT CO | INDEX | MASK
|
||||
|
||||
struct SculptSession;
|
||||
|
||||
void BKE_pbvh_ensure_proxyarrays(
|
||||
struct SculptSession *ss, PBVH *pbvh, PBVHNode **nodes, int totnode, int mask);
|
||||
void BKE_pbvh_load_proxyarrays(PBVH *pbvh, PBVHNode **nodes, int totnode, int mask);
|
||||
|
||||
void BKE_pbvh_ensure_proxyarray(
|
||||
struct SculptSession *ss,
|
||||
struct PBVH *pbvh,
|
||||
struct PBVHNode *node,
|
||||
int mask,
|
||||
struct GHash
|
||||
*vert_node_map, // vert_node_map maps vertex SculptVertRefs to PBVHNode indices; optional
|
||||
bool check_indexmap,
|
||||
bool force_update);
|
||||
void BKE_pbvh_gather_proxyarray(PBVH *pbvh, PBVHNode **nodes, int totnode);
|
||||
|
||||
void BKE_pbvh_free_proxyarray(struct PBVH *pbvh, struct PBVHNode *node);
|
||||
void BKE_pbvh_update_proxyvert(struct PBVH *pbvh, struct PBVHNode *node, ProxyVertUpdateRec *rec);
|
||||
ProxyVertArray *BKE_pbvh_get_proxyarrays(struct PBVH *pbvh, struct PBVHNode *node);
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
float (*co)[3];
|
||||
} PBVHProxyNode;
|
||||
|
||||
typedef struct {
|
||||
float (*color)[4];
|
||||
int size;
|
||||
} PBVHColorBufferNode;
|
||||
|
||||
typedef enum {
|
||||
@@ -78,6 +230,15 @@ typedef enum {
|
||||
|
||||
PBVH_UpdateTopology = 1 << 13,
|
||||
PBVH_UpdateColor = 1 << 14,
|
||||
PBVH_Delete = 1 << 15,
|
||||
PBVH_UpdateCurvatureDir = 1 << 16,
|
||||
PBVH_UpdateTris = 1 << 17,
|
||||
PBVH_RebuildNodeVerts = 1 << 18,
|
||||
|
||||
/* tri areas are not guaranteed to be up to date, tools should
|
||||
update all nodes on first step of brush*/
|
||||
PBVH_UpdateTriAreas = 1 << 19,
|
||||
PBVH_UpdateOtherVerts = 1 << 20
|
||||
} PBVHNodeFlags;
|
||||
|
||||
typedef struct PBVHFrustumPlanes {
|
||||
@@ -98,6 +259,9 @@ typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *
|
||||
|
||||
typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float *tmin);
|
||||
|
||||
void BKE_pbvh_get_nodes(PBVH *pbvh, int flag, PBVHNode ***r_array, int *r_totnode);
|
||||
PBVHNode *BKE_pbvh_get_node(PBVH *pbvh, int node);
|
||||
|
||||
/* Building */
|
||||
|
||||
PBVH *BKE_pbvh_new(void);
|
||||
@@ -106,27 +270,57 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
|
||||
const struct MPoly *mpoly,
|
||||
const struct MLoop *mloop,
|
||||
struct MVert *verts,
|
||||
struct MDynTopoVert *mdyntopo_verts,
|
||||
int totvert,
|
||||
struct CustomData *vdata,
|
||||
struct CustomData *ldata,
|
||||
struct CustomData *pdata,
|
||||
const struct MLoopTri *looptri,
|
||||
int looptri_num);
|
||||
int looptri_num,
|
||||
bool fast_draw);
|
||||
void BKE_pbvh_build_grids(PBVH *pbvh,
|
||||
struct CCGElem **grids,
|
||||
int totgrid,
|
||||
struct CCGKey *key,
|
||||
void **gridfaces,
|
||||
struct DMFlagMat *flagmats,
|
||||
unsigned int **grid_hidden);
|
||||
unsigned int **grid_hidden,
|
||||
bool fast_draw);
|
||||
void BKE_pbvh_build_bmesh(PBVH *pbvh,
|
||||
struct BMesh *bm,
|
||||
bool smooth_shading,
|
||||
struct BMLog *log,
|
||||
const int cd_vert_node_offset,
|
||||
const int cd_face_node_offset);
|
||||
const int cd_face_node_offset,
|
||||
const int cd_dyn_vert,
|
||||
const int cd_face_areas,
|
||||
bool fast_draw);
|
||||
void BKE_pbvh_update_offsets(PBVH *pbvh,
|
||||
const int cd_vert_node_offset,
|
||||
const int cd_face_node_offset,
|
||||
const int cd_dyn_vert,
|
||||
const int cd_face_areas);
|
||||
void BKE_pbvh_free(PBVH *pbvh);
|
||||
|
||||
void BKE_pbvh_set_bm_log(PBVH *pbvh, struct BMLog *log);
|
||||
|
||||
/** update original data, only data whose r_** parameters are passed in will be updated*/
|
||||
void BKE_pbvh_bmesh_update_origvert(
|
||||
PBVH *pbvh, struct BMVert *v, float **r_co, float **r_no, float **r_color, bool log_undo);
|
||||
void BKE_pbvh_update_origcolor_bmesh(PBVH *pbvh, PBVHNode *node);
|
||||
void BKE_pbvh_update_origco_bmesh(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
/**
|
||||
checks if original data needs to be updated for v, and if so updates it. Stroke_id
|
||||
is provided by the sculpt code and is used to detect updates. The reason we do it
|
||||
inside the verts and not in the nodes is to allow splitting of the pbvh during the stroke.
|
||||
*/
|
||||
bool BKE_pbvh_bmesh_check_origdata(PBVH *pbvh, struct BMVert *v, int stroke_id);
|
||||
|
||||
/** used so pbvh can differentiate between different strokes,
|
||||
see BKE_pbvh_bmesh_check_origdata */
|
||||
void BKE_pbvh_set_stroke_id(PBVH *pbvh, int stroke_id);
|
||||
|
||||
/* Hierarchical Search in the BVH, two methods:
|
||||
* - for each hit calling a callback
|
||||
* - gather nodes in an array (easy to multithread) */
|
||||
@@ -150,7 +344,8 @@ void BKE_pbvh_raycast(PBVH *pbvh,
|
||||
void *data,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
bool original);
|
||||
bool original,
|
||||
int stroke_id);
|
||||
|
||||
bool BKE_pbvh_node_raycast(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
@@ -159,12 +354,16 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
int *hit_count,
|
||||
float *depth,
|
||||
int *active_vertex_index,
|
||||
int *active_face_grid_index,
|
||||
float *face_normal);
|
||||
float *back_depth,
|
||||
SculptVertRef *active_vertex_index,
|
||||
SculptFaceRef *active_face_grid_index,
|
||||
float *face_normal,
|
||||
int stroke_id);
|
||||
|
||||
bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
|
||||
bool BKE_pbvh_bmesh_node_raycast_detail(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
const float ray_start[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
float *depth,
|
||||
@@ -189,7 +388,8 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
float *depth,
|
||||
float *dist_sq);
|
||||
float *dist_sq,
|
||||
int stroke_id);
|
||||
|
||||
/* Drawing */
|
||||
|
||||
@@ -238,22 +438,60 @@ int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh);
|
||||
|
||||
/* Only valid for type == PBVH_BMESH */
|
||||
struct BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
|
||||
void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
|
||||
void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size, float detail_range);
|
||||
|
||||
typedef enum {
|
||||
PBVH_Subdivide = 1,
|
||||
PBVH_Collapse = 2,
|
||||
PBVH_Subdivide = 1 << 0,
|
||||
PBVH_Collapse = 1 << 1,
|
||||
PBVH_Cleanup = 1 << 2, // dissolve verts surrounded by either 3 or 4 triangles then triangulate
|
||||
PBVH_LocalSubdivide = 1 << 3,
|
||||
PBVH_LocalCollapse = 1 << 4
|
||||
} PBVHTopologyUpdateMode;
|
||||
bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
||||
PBVHTopologyUpdateMode mode,
|
||||
const float center[3],
|
||||
const float view_normal[3],
|
||||
float radius,
|
||||
const bool use_frontface,
|
||||
const bool use_projected);
|
||||
|
||||
typedef float (*DyntopoMaskCB)(SculptVertRef vertex, void *userdata);
|
||||
|
||||
bool BKE_pbvh_bmesh_update_topology(
|
||||
PBVH *pbvh,
|
||||
PBVHTopologyUpdateMode mode,
|
||||
const float center[3],
|
||||
const float view_normal[3],
|
||||
float radius,
|
||||
const bool use_frontface,
|
||||
const bool use_projected,
|
||||
int symaxis,
|
||||
bool updatePBVH,
|
||||
DyntopoMaskCB mask_cb,
|
||||
void *mask_cb_data,
|
||||
int custom_max_steps); // if 0, will use defaul hueristics for max steps
|
||||
|
||||
bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
|
||||
bool (*searchcb)(PBVHNode *node, void *data),
|
||||
void (*undopush)(PBVHNode *node, void *data),
|
||||
void *searchdata,
|
||||
PBVHTopologyUpdateMode mode,
|
||||
const float center[3],
|
||||
const float view_normal[3],
|
||||
float radius,
|
||||
const bool use_frontface,
|
||||
const bool use_projected,
|
||||
int sym_axis,
|
||||
bool updatePBVH,
|
||||
DyntopoMaskCB mask_cb,
|
||||
void *mask_cb_data);
|
||||
/* Node Access */
|
||||
|
||||
void BKE_pbvh_check_tri_areas(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
// updates boundaries and valences for whole mesh
|
||||
void BKE_pbvh_bmesh_on_mesh_change(PBVH *pbvh);
|
||||
bool BKE_pbvh_bmesh_check_valence(PBVH *pbvh, SculptVertRef vertex);
|
||||
void BKE_pbvh_bmesh_update_valence(int cd_dyn_vert, SculptVertRef vertex);
|
||||
void BKE_pbvh_bmesh_update_all_valence(PBVH *pbvh);
|
||||
void BKE_pbvh_bmesh_flag_all_disk_sort(PBVH *pbvh);
|
||||
bool BKE_pbvh_bmesh_mark_update_valence(PBVH *pbvh, SculptVertRef vertex);
|
||||
|
||||
void BKE_pbvh_node_mark_update_tri_area(PBVHNode *node);
|
||||
void BKE_pbvh_update_all_tri_areas(PBVH *pbvh);
|
||||
void BKE_pbvh_node_mark_update(PBVHNode *node);
|
||||
void BKE_pbvh_node_mark_update_mask(PBVHNode *node);
|
||||
void BKE_pbvh_node_mark_update_color(PBVHNode *node);
|
||||
@@ -292,10 +530,14 @@ bool BKE_pbvh_node_frustum_contain_AABB(PBVHNode *node, void *frustum);
|
||||
/* test if AABB is at least partially outside the PBVHFrustumPlanes volume */
|
||||
bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *frustum);
|
||||
|
||||
struct GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
|
||||
struct GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
|
||||
struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
|
||||
void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm, PBVHNode *node);
|
||||
struct TableGSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
|
||||
struct TableGSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
|
||||
struct TableGSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
|
||||
|
||||
void BKE_pbvh_bmesh_regen_node_verts(PBVH *pbvh);
|
||||
void BKE_pbvh_bmesh_mark_node_regen(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
// now generated PBVHTris
|
||||
void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
|
||||
|
||||
/* Update Bounding Box/Redraw and clear flags */
|
||||
@@ -343,6 +585,7 @@ typedef struct PBVHVertexIter {
|
||||
int gy;
|
||||
int i;
|
||||
int index;
|
||||
SculptVertRef vertex;
|
||||
bool respect_hide;
|
||||
|
||||
/* grid */
|
||||
@@ -362,10 +605,14 @@ typedef struct PBVHVertexIter {
|
||||
float *vmask;
|
||||
|
||||
/* bmesh */
|
||||
struct GSetIterator bm_unique_verts;
|
||||
struct GSetIterator bm_other_verts;
|
||||
int bi;
|
||||
struct TableGSet *bm_cur_set;
|
||||
struct TableGSet *bm_unique_verts, *bm_other_verts;
|
||||
|
||||
struct CustomData *bm_vdata;
|
||||
int cd_dyn_vert;
|
||||
int cd_vert_mask_offset;
|
||||
int cd_vcol_offset;
|
||||
|
||||
/* result: these are all computed in the macro, but we assume
|
||||
* that compiler optimization's will skip the ones we don't use */
|
||||
@@ -379,6 +626,8 @@ typedef struct PBVHVertexIter {
|
||||
bool visible;
|
||||
} PBVHVertexIter;
|
||||
|
||||
#define BKE_PBVH_DYNVERT(cd_dyn_vert, v) ((MDynTopoVert *)BM_ELEM_CD_GET_VOID_P(v, cd_dyn_vert))
|
||||
|
||||
void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
|
||||
|
||||
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode) \
|
||||
@@ -388,7 +637,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
||||
if (vi.grids) { \
|
||||
vi.width = vi.gridsize; \
|
||||
vi.height = vi.gridsize; \
|
||||
vi.index = vi.grid_indices[vi.g] * vi.key.grid_area - 1; \
|
||||
vi.vertex.i = vi.index = vi.grid_indices[vi.g] * vi.key.grid_area - 1; \
|
||||
vi.grid = vi.grids[vi.grid_indices[vi.g]]; \
|
||||
if (mode == PBVH_ITER_UNIQUE) { \
|
||||
vi.gh = vi.grid_hidden[vi.grid_indices[vi.g]]; \
|
||||
@@ -407,6 +656,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
||||
vi.mask = vi.key.has_mask ? CCG_elem_mask(&vi.key, vi.grid) : NULL; \
|
||||
vi.grid = CCG_elem_next(&vi.key, vi.grid); \
|
||||
vi.index++; \
|
||||
vi.vertex.i++; \
|
||||
vi.visible = true; \
|
||||
if (vi.gh) { \
|
||||
if (BLI_BITMAP_TEST(vi.gh, vi.gy * vi.gridsize + vi.gx)) { \
|
||||
@@ -427,7 +677,7 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
||||
} \
|
||||
vi.co = vi.mvert->co; \
|
||||
vi.no = vi.mvert->no; \
|
||||
vi.index = vi.vert_indices[vi.i]; \
|
||||
vi.index = vi.vertex.i = vi.vert_indices[vi.i]; \
|
||||
if (vi.vmask) { \
|
||||
vi.mask = &vi.vmask[vi.index]; \
|
||||
} \
|
||||
@@ -436,22 +686,41 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
if (!BLI_gsetIterator_done(&vi.bm_unique_verts)) { \
|
||||
vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_unique_verts); \
|
||||
BLI_gsetIterator_step(&vi.bm_unique_verts); \
|
||||
BMVert *bv = NULL; \
|
||||
while (!bv) { \
|
||||
if (!vi.bm_cur_set->elems || vi.bi >= vi.bm_cur_set->cur) { \
|
||||
if (vi.bm_cur_set != vi.bm_other_verts && mode != PBVH_ITER_UNIQUE) { \
|
||||
vi.bm_cur_set = vi.bm_other_verts; \
|
||||
vi.bi = 0; \
|
||||
if (!vi.bm_cur_set->elems || vi.bi >= vi.bm_other_verts->cur) { \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
bv = vi.bm_cur_set->elems[vi.bi++]; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_other_verts); \
|
||||
BLI_gsetIterator_step(&vi.bm_other_verts); \
|
||||
if (!bv) { \
|
||||
continue; \
|
||||
} \
|
||||
vi.bm_vert = bv; \
|
||||
if (vi.cd_vcol_offset >= 0) { \
|
||||
MPropCol *vcol = BM_ELEM_CD_GET_VOID_P(bv, vi.cd_vcol_offset); \
|
||||
vi.col = vcol->color; \
|
||||
} \
|
||||
vi.vertex.i = (intptr_t)bv; \
|
||||
vi.index = BM_elem_index_get(vi.bm_vert); \
|
||||
vi.visible = !BM_elem_flag_test_bool(vi.bm_vert, BM_ELEM_HIDDEN); \
|
||||
if (mode == PBVH_ITER_UNIQUE && !vi.visible) { \
|
||||
continue; \
|
||||
} \
|
||||
vi.co = vi.bm_vert->co; \
|
||||
vi.fno = vi.bm_vert->no; \
|
||||
vi.index = BM_elem_index_get(vi.bm_vert); \
|
||||
vi.mask = BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \
|
||||
vi.mask = (float *)BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \
|
||||
}
|
||||
|
||||
#define BKE_pbvh_vertex_iter_end \
|
||||
@@ -460,24 +729,32 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
#define BKE_pbvh_vertex_index_to_table(pbvh, v) \
|
||||
(BKE_pbvh_type(pbvh) == PBVH_BMESH && v.i != -1 ? BM_elem_index_get((BMVert *)(v.i)) : (v.i))
|
||||
SculptVertRef BKE_pbvh_table_index_to_vertex(PBVH *pbvh, int idx);
|
||||
|
||||
#define BKE_pbvh_edge_index_to_table(pbvh, v) \
|
||||
(BKE_pbvh_type(pbvh) == PBVH_BMESH && v.i != -1 ? BM_elem_index_get((BMEdge *)(v.i)) : (v.i))
|
||||
SculptEdgeRef BKE_pbvh_table_index_to_edge(PBVH *pbvh, int idx);
|
||||
|
||||
#define BKE_pbvh_face_index_to_table(pbvh, v) \
|
||||
(BKE_pbvh_type(pbvh) == PBVH_BMESH && v.i != -1 ? BM_elem_index_get((BMFace *)(v.i)) : (v.i))
|
||||
SculptFaceRef BKE_pbvh_table_index_to_face(PBVH *pbvh, int idx);
|
||||
|
||||
void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
|
||||
void BKE_pbvh_node_free_proxies(PBVHNode *node);
|
||||
PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node);
|
||||
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot);
|
||||
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
|
||||
int (**r_orco_tris)[3],
|
||||
int *r_orco_tris_num,
|
||||
float (**r_orco_coords)[3]);
|
||||
|
||||
bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
// void BKE_pbvh_node_BB_reset(PBVHNode *node);
|
||||
// void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
|
||||
|
||||
bool pbvh_has_mask(const PBVH *pbvh);
|
||||
bool BKE_pbvh_draw_mask(const PBVH *pbvh);
|
||||
void pbvh_show_mask_set(PBVH *pbvh, bool show_mask);
|
||||
|
||||
bool pbvh_has_face_sets(PBVH *pbvh);
|
||||
bool BKE_pbvh_draw_face_sets(PBVH *pbvh);
|
||||
void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets);
|
||||
|
||||
/* Parallelization */
|
||||
@@ -490,6 +767,150 @@ struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh);
|
||||
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node);
|
||||
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh);
|
||||
|
||||
int BKE_pbvh_get_node_index(PBVH *pbvh, PBVHNode *node);
|
||||
int BKE_pbvh_get_node_id(PBVH *pbvh, PBVHNode *node);
|
||||
void BKE_pbvh_set_flat_vcol_shading(PBVH *pbvh, bool value);
|
||||
|
||||
#define DYNTOPO_CD_INTERP
|
||||
|
||||
void SCULPT_update_flat_vcol_shading(struct Object *ob, struct Scene *scene);
|
||||
|
||||
void BKE_pbvh_curvature_update_set(PBVHNode *node, bool state);
|
||||
bool BKE_pbvh_curvature_update_get(PBVHNode *node);
|
||||
|
||||
int BKE_pbvh_get_totnodes(PBVH *pbvh);
|
||||
|
||||
bool BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node);
|
||||
PBVHTriBuf *BKE_pbvh_bmesh_get_tris(PBVH *pbvh, PBVHNode *node);
|
||||
void BKE_pbvh_bmesh_free_tris(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
/*recalculates boundary flags for *all* vertices. used by
|
||||
symmetrize.*/
|
||||
void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh);
|
||||
|
||||
void BKE_pbvh_bmesh_remove_face(PBVH *pbvh, struct BMFace *f, bool log_face);
|
||||
void BKE_pbvh_bmesh_remove_vertex(PBVH *pbvh, struct BMVert *v, bool log_vert);
|
||||
void BKE_pbvh_bmesh_add_face(PBVH *pbvh, struct BMFace *f, bool log_face, bool force_tree_walk);
|
||||
|
||||
// note that e_tri and f_example are allowed to be NULL
|
||||
struct BMFace *BKE_pbvh_face_create_bmesh(PBVH *pbvh,
|
||||
struct BMVert *v_tri[3],
|
||||
struct BMEdge *e_tri[3],
|
||||
const struct BMFace *f_example);
|
||||
|
||||
// if node is NULL, one will be foudn in the pbvh, which potentially can be slow
|
||||
struct BMVert *BKE_pbvh_vert_create_bmesh(
|
||||
PBVH *pbvh, float co[3], float no[3], PBVHNode *node, struct BMVert *v_example);
|
||||
PBVHNode *BKE_pbvh_node_from_face_bmesh(PBVH *pbvh, struct BMFace *f);
|
||||
PBVHNode *BKE_pbvh_node_from_index(PBVH *pbvh, int node_i);
|
||||
|
||||
struct BMesh *BKE_pbvh_reorder_bmesh(PBVH *pbvh);
|
||||
void BKE_pbvh_update_vert_boundary(int cd_dyn_vert,
|
||||
int cd_faceset_offset,
|
||||
struct BMVert *v,
|
||||
int symmetry);
|
||||
|
||||
#define DYNTOPO_DYNAMIC_TESS
|
||||
|
||||
PBVHNode *BKE_pbvh_get_node_leaf_safe(PBVH *pbvh, int i);
|
||||
|
||||
void BKE_pbvh_get_vert_face_areas(PBVH *pbvh, SculptVertRef vertex, float *r_areas, int valence);
|
||||
void BKE_pbvh_set_symmetry(PBVH *pbvh, int symmetry, int boundary_symmetry);
|
||||
|
||||
#if 0
|
||||
typedef enum {
|
||||
SCULPT_TEXTURE_UV = 1 << 0, // per-uv
|
||||
// SCULPT_TEXTURE_PTEX?
|
||||
} SculptTextureType;
|
||||
|
||||
typedef int TexLayerRef;
|
||||
|
||||
/*
|
||||
Texture points are texels projected into 3d.
|
||||
*/
|
||||
typedef intptr_t TexPointRef;
|
||||
|
||||
void *BKE_pbvh_get_tex_settings(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
void *BKE_pbvh_get_tex_data(PBVH *pbvh, PBVHNode *node, TexPointRef vdm);
|
||||
|
||||
typedef struct SculptTextureDef {
|
||||
SculptTextureType type;
|
||||
int settings_size;
|
||||
|
||||
void (*build_begin)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
|
||||
/*vdms can cache data per node, which is freed to maintain memory limit.
|
||||
they store cache in the same structure they return in buildNodeData.*/
|
||||
void (*freeCachedData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
void (*ensuredCachedData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
|
||||
/*builds all data that isn't cached.*/
|
||||
void *(*buildNodeData)(PBVH *pbvh, PBVHNode *node);
|
||||
bool (*validate)(PBVH *pbvh, TexLayerRef vdm);
|
||||
|
||||
void (*getPointsFromNode)(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
TexPointRef **r_ids,
|
||||
float ***r_cos,
|
||||
float ***r_nos,
|
||||
int *r_totpoint);
|
||||
void (*releaseNodePoints)(
|
||||
PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, float **cos, float **nos);
|
||||
|
||||
# if 0
|
||||
int (*getTrisFromNode)(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
TexPointRef *((*r_tris)[3]),
|
||||
TexPointRef **r_ids,
|
||||
int tottri,
|
||||
int totid);
|
||||
void (*getTriInterpWeightsFromNode)(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
float *((*r_tris)[3]),
|
||||
SculptLoopRef ***r_src_loops,
|
||||
int tottri,
|
||||
int totloop);
|
||||
int (*getTriCount)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm);
|
||||
# endif
|
||||
|
||||
void (*getPointNeighbors)(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
TexPointRef id,
|
||||
TexPointRef **r_neighbor_ids,
|
||||
int *r_totneighbor,
|
||||
int maxneighbors,
|
||||
TexPointRef **r_duplicates_id,
|
||||
int r_totduplicate,
|
||||
int maxduplicates);
|
||||
void (*getPointValence)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef id);
|
||||
void (*freeNodeData)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, void *settings);
|
||||
|
||||
void (*getPointsFromIds)(
|
||||
PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
|
||||
|
||||
/*displacement texture stuff*/
|
||||
// can be tangent, object space displacement, whatever
|
||||
void (*worldToDelta)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
|
||||
void (*deltaToWorld)(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm, TexPointRef *ids, int totid);
|
||||
} SculptDisplacementDef;
|
||||
|
||||
typedef struct SculptLayerEntry {
|
||||
char name[64];
|
||||
int type;
|
||||
void *settings;
|
||||
float factor;
|
||||
struct SculptLayerEntry *parent;
|
||||
} SculptLayerEntry;
|
||||
|
||||
#endif
|
||||
|
||||
int BKE_pbvh_do_fset_symmetry(int fset, const int symflag, const float *co);
|
||||
bool BKE_pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -124,6 +124,7 @@ set(SRC
|
||||
intern/displist.cc
|
||||
intern/displist_tangent.c
|
||||
intern/dynamicpaint.c
|
||||
intern/dyntopo.c
|
||||
intern/editlattice.c
|
||||
intern/editmesh.c
|
||||
intern/editmesh_bvh.c
|
||||
@@ -235,6 +236,7 @@ set(SRC
|
||||
intern/particle_system.c
|
||||
intern/pbvh.c
|
||||
intern/pbvh_bmesh.c
|
||||
intern/pbvh_displacement.c
|
||||
intern/pointcache.c
|
||||
intern/pointcloud.cc
|
||||
intern/preferences.c
|
||||
@@ -287,6 +289,9 @@ set(SRC
|
||||
intern/workspace.c
|
||||
intern/world.c
|
||||
intern/writeavi.c
|
||||
intern/brush_engine.c
|
||||
intern/brush_engine_presets.c
|
||||
intern/curvemapping_cache.c
|
||||
|
||||
BKE_DerivedMesh.h
|
||||
BKE_action.h
|
||||
@@ -335,6 +340,7 @@ set(SRC
|
||||
BKE_curveprofile.h
|
||||
BKE_customdata.h
|
||||
BKE_customdata_file.h
|
||||
BKE_curvemapping_cache.h
|
||||
BKE_data_transfer.h
|
||||
BKE_deform.h
|
||||
BKE_displist.h
|
||||
@@ -449,6 +455,7 @@ set(SRC
|
||||
BKE_workspace.h
|
||||
BKE_world.h
|
||||
BKE_writeavi.h
|
||||
BKE_brush_engine.h
|
||||
|
||||
nla_private.h
|
||||
particle_private.h
|
||||
@@ -794,3 +801,75 @@ if(WITH_GTESTS)
|
||||
include(GTestTesting)
|
||||
blender_add_test_lib(bf_blenkernel_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB}")
|
||||
endif()
|
||||
|
||||
if(false)
|
||||
set(PBVH_CACHE_TEST_INC
|
||||
.
|
||||
../blenfont
|
||||
../blenlib
|
||||
../blenloader
|
||||
../blentranslation
|
||||
../bmesh
|
||||
../depsgraph
|
||||
../draw
|
||||
../functions
|
||||
../gpencil_modifiers
|
||||
../gpu
|
||||
../ikplugin
|
||||
../imbuf
|
||||
../makesdna
|
||||
../makesrna
|
||||
../modifiers
|
||||
../nodes
|
||||
../render
|
||||
../sequencer
|
||||
../shader_fx
|
||||
../simulation
|
||||
../../../intern/eigen
|
||||
../../../intern/ghost
|
||||
../../../intern/glew-mx
|
||||
../../../intern/guardedalloc
|
||||
../../../intern/iksolver/extern
|
||||
../../../intern/atomic
|
||||
../../../intern/clog
|
||||
../../../intern/libmv
|
||||
../../../intern/mantaflow/extern
|
||||
../../../intern/memutil
|
||||
../../../intern/mikktspace
|
||||
../../../intern/opensubdiv
|
||||
../../../extern/curve_fit_nd
|
||||
)
|
||||
|
||||
set(PBVH_CACHE_TEST_SRC
|
||||
intern/pbvh_cache_test_main.c
|
||||
)
|
||||
|
||||
setup_libdirs()
|
||||
|
||||
add_executable(pbvh_cache_test ${PBVH_CACHE_TEST_SRC} ${PBVH_CACHE_TEST_INC})
|
||||
setup_platform_linker_flags(pbvh_cache_test)
|
||||
|
||||
target_link_libraries(pbvh_cache_test bf_blenkernel bf_bmesh bf_intern_ghost bf_blenlib bf_intern_guardedalloc)
|
||||
|
||||
if(WIN32)
|
||||
set_target_properties(pbvh_cache_test PROPERTIES VS_GLOBAL_VcpkgEnabled "false")
|
||||
set_target_properties(pbvh_cache_test PROPERTIES
|
||||
PDB_NAME "pbvh_cache_test_private"
|
||||
PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
|
||||
if(WITH_WINDOWS_PDB AND WITH_WINDOWS_STRIPPED_PDB)
|
||||
# This is slightly messy, but single target generators like ninja will not have the
|
||||
# CMAKE_CFG_INTDIR variable and multitarget generators like msbuild will not have
|
||||
# CMAKE_BUILD_TYPE. This can be simplified by target_link_options and the $<CONFIG>
|
||||
# generator expression in newer cmake (2.13+) but until that time this fill have suffice.
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
set_property(TARGET pbvh_cache_test APPEND_STRING PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/pbvh_cache_test_public.pdb")
|
||||
else()
|
||||
set_property(TARGET pbvh_cache_test APPEND_STRING PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/pbvh_cache_test_public.pdb")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(pbvh_cache_test Vfw32.lib Imm32.lib Version.lib Comctl32.lib Shcore.lib Pathcch.lib)
|
||||
endif()
|
||||
endif()
|
||||
|
@@ -1140,7 +1140,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
||||
unsupported = true;
|
||||
}
|
||||
|
||||
if (scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM) {
|
||||
if (scene->toolsettings->sculpt && scene->toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM) {
|
||||
unsupported |= (mti->type != eModifierTypeType_OnlyDeform);
|
||||
}
|
||||
|
||||
|
@@ -425,7 +425,7 @@ void BKE_animdata_copy_id_action(Main *bmain, ID *id)
|
||||
|
||||
void BKE_animdata_duplicate_id_action(struct Main *bmain,
|
||||
struct ID *id,
|
||||
const eDupli_ID_Flags duplicate_flags)
|
||||
const uint duplicate_flags)
|
||||
{
|
||||
if (duplicate_flags & USER_DUP_ACT) {
|
||||
animdata_copy_id_action(bmain, id, true, (duplicate_flags & USER_DUP_LINKED_ID) != 0);
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_brush_engine.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_gpencil.h"
|
||||
@@ -85,6 +86,8 @@ static void brush_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
|
||||
}
|
||||
|
||||
brush_dst->curve = BKE_curvemapping_copy(brush_src->curve);
|
||||
brush_dst->pressure_size_curve = BKE_curvemapping_copy(brush_src->pressure_size_curve);
|
||||
brush_dst->pressure_strength_curve = BKE_curvemapping_copy(brush_src->pressure_strength_curve);
|
||||
if (brush_src->gpencil_settings != NULL) {
|
||||
brush_dst->gpencil_settings = MEM_dupallocN(brush_src->gpencil_settings);
|
||||
brush_dst->gpencil_settings->curve_sensitivity = BKE_curvemapping_copy(
|
||||
@@ -119,6 +122,8 @@ static void brush_free_data(ID *id)
|
||||
IMB_freeImBuf(brush->icon_imbuf);
|
||||
}
|
||||
BKE_curvemapping_free(brush->curve);
|
||||
BKE_curvemapping_free(brush->pressure_size_curve);
|
||||
BKE_curvemapping_free(brush->pressure_strength_curve);
|
||||
|
||||
if (brush->gpencil_settings != NULL) {
|
||||
BKE_curvemapping_free(brush->gpencil_settings->curve_sensitivity);
|
||||
@@ -138,6 +143,10 @@ static void brush_free_data(ID *id)
|
||||
MEM_SAFE_FREE(brush->gradient);
|
||||
|
||||
BKE_previewimg_free(&(brush->preview));
|
||||
|
||||
if (brush->channels) {
|
||||
BKE_brush_channelset_free(brush->channels);
|
||||
}
|
||||
}
|
||||
|
||||
static void brush_make_local(Main *bmain, ID *id, const int flags)
|
||||
@@ -217,7 +226,7 @@ static void brush_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
BKE_texture_mtex_foreach_id(data, &brush->mask_mtex);
|
||||
}
|
||||
|
||||
static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
ATTR_NO_OPT static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Brush *brush = (Brush *)id;
|
||||
|
||||
@@ -227,6 +236,12 @@ static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_addres
|
||||
if (brush->curve) {
|
||||
BKE_curvemapping_blend_write(writer, brush->curve);
|
||||
}
|
||||
if (brush->pressure_size_curve) {
|
||||
BKE_curvemapping_blend_write(writer, brush->pressure_size_curve);
|
||||
}
|
||||
if (brush->pressure_strength_curve) {
|
||||
BKE_curvemapping_blend_write(writer, brush->pressure_strength_curve);
|
||||
}
|
||||
|
||||
if (brush->gpencil_settings) {
|
||||
BLO_write_struct(writer, BrushGpencilSettings, brush->gpencil_settings);
|
||||
@@ -262,15 +277,82 @@ static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_addres
|
||||
if (brush->gradient) {
|
||||
BLO_write_struct(writer, ColorBand, brush->gradient);
|
||||
}
|
||||
|
||||
if (brush->channels) {
|
||||
BKE_brush_channelset_write(writer, brush->channels);
|
||||
}
|
||||
}
|
||||
|
||||
static void brush_reset_input_curve(CurveMapping *cumap)
|
||||
{
|
||||
cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
|
||||
cumap->preset = CURVE_PRESET_LINE;
|
||||
|
||||
CurveMap *cuma = cumap->cm;
|
||||
BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
|
||||
BKE_curvemapping_changed(cumap, false);
|
||||
BKE_curvemapping_init(cumap);
|
||||
}
|
||||
|
||||
void BKE_brush_default_input_curves_set(Brush *brush)
|
||||
{
|
||||
if (brush->pressure_size_curve) {
|
||||
BKE_curvemapping_free(brush->pressure_size_curve);
|
||||
}
|
||||
brush->pressure_size_curve = BKE_curvemapping_add(1, 0, 0, 1, 1);
|
||||
brush_reset_input_curve(brush->pressure_size_curve);
|
||||
|
||||
if (brush->pressure_strength_curve) {
|
||||
BKE_curvemapping_free(brush->pressure_strength_curve);
|
||||
}
|
||||
brush->pressure_strength_curve = BKE_curvemapping_add(1, 0, 0, 1, 1);
|
||||
brush_reset_input_curve(brush->pressure_strength_curve);
|
||||
}
|
||||
|
||||
static void brush_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
{
|
||||
Brush *brush = (Brush *)id;
|
||||
|
||||
if (brush->channels) {
|
||||
BLO_read_data_address(reader, &brush->channels);
|
||||
|
||||
BKE_brush_channelset_read(reader, brush->channels);
|
||||
BKE_brush_builtin_patch(brush, brush->sculpt_tool);
|
||||
}
|
||||
else {
|
||||
BKE_brush_builtin_create(brush, brush->sculpt_tool);
|
||||
}
|
||||
|
||||
if (brush->dyntopo.radius_scale == 0.0f) {
|
||||
brush->dyntopo.radius_scale = 1.0f;
|
||||
brush->dyntopo.inherit |= DYNTOPO_INHERIT_RADIUS_SCALE;
|
||||
}
|
||||
|
||||
// detect old file data
|
||||
if (brush->autosmooth_radius_factor == 0.0f) {
|
||||
brush->autosmooth_radius_factor = 1.0f;
|
||||
}
|
||||
|
||||
if (brush->topology_rake_radius_factor == 0.0f) {
|
||||
brush->topology_rake_radius_factor = 1.0f;
|
||||
}
|
||||
|
||||
if (brush->autosmooth_spacing == 0.0f) {
|
||||
brush->autosmooth_spacing = 12;
|
||||
}
|
||||
|
||||
if (brush->topology_rake_spacing == 0.0f) {
|
||||
brush->topology_rake_spacing = 12;
|
||||
brush->topology_rake_projection = 1.0f;
|
||||
}
|
||||
|
||||
/* Falloff curve. */
|
||||
BLO_read_data_address(reader, &brush->curve);
|
||||
|
||||
/* Input Curves. */
|
||||
BLO_read_data_address(reader, &brush->pressure_size_curve);
|
||||
BLO_read_data_address(reader, &brush->pressure_strength_curve);
|
||||
|
||||
BLO_read_data_address(reader, &brush->gradient);
|
||||
|
||||
if (brush->curve) {
|
||||
@@ -280,6 +362,20 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
BKE_brush_curve_preset(brush, CURVE_PRESET_SHARP);
|
||||
}
|
||||
|
||||
if (brush->pressure_size_curve) {
|
||||
BKE_curvemapping_blend_read(reader, brush->pressure_size_curve);
|
||||
}
|
||||
else {
|
||||
BKE_brush_default_input_curves_set(brush);
|
||||
}
|
||||
|
||||
if (brush->pressure_strength_curve) {
|
||||
BKE_curvemapping_blend_read(reader, brush->pressure_strength_curve);
|
||||
}
|
||||
else {
|
||||
BKE_brush_default_input_curves_set(brush);
|
||||
}
|
||||
|
||||
/* grease pencil */
|
||||
BLO_read_data_address(reader, &brush->gpencil_settings);
|
||||
if (brush->gpencil_settings != NULL) {
|
||||
@@ -464,7 +560,13 @@ static void brush_defaults(Brush *brush)
|
||||
FROM_DEFAULT(alpha);
|
||||
FROM_DEFAULT(hardness);
|
||||
FROM_DEFAULT(autosmooth_factor);
|
||||
FROM_DEFAULT(autosmooth_projection);
|
||||
FROM_DEFAULT(autosmooth_radius_factor);
|
||||
FROM_DEFAULT(autosmooth_spacing);
|
||||
FROM_DEFAULT(topology_rake_factor);
|
||||
FROM_DEFAULT(topology_rake_radius_factor);
|
||||
FROM_DEFAULT(topology_rake_projection);
|
||||
FROM_DEFAULT(topology_rake_spacing);
|
||||
FROM_DEFAULT(crease_pinch_factor);
|
||||
FROM_DEFAULT(normal_radius_factor);
|
||||
FROM_DEFAULT(wet_paint_radius_factor);
|
||||
@@ -495,6 +597,7 @@ static void brush_defaults(Brush *brush)
|
||||
FROM_DEFAULT(stencil_dimension);
|
||||
FROM_DEFAULT(mtex);
|
||||
FROM_DEFAULT(mask_mtex);
|
||||
FROM_DEFAULT(dyntopo);
|
||||
|
||||
#undef FROM_DEFAULT
|
||||
#undef FROM_DEFAULT_PTR
|
||||
@@ -1662,6 +1765,8 @@ void BKE_brush_debug_print_state(Brush *br)
|
||||
BR_TEST(plane_offset, f);
|
||||
|
||||
BR_TEST(autosmooth_factor, f);
|
||||
BR_TEST(autosmooth_projection, f);
|
||||
BR_TEST(autosmooth_radius_factor, f);
|
||||
|
||||
BR_TEST(topology_rake_factor, f);
|
||||
|
||||
@@ -1693,8 +1798,19 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
* settings used by a brush: */
|
||||
// BKE_brush_debug_print_state(br);
|
||||
|
||||
BKE_brush_builtin_create(br, br->sculpt_tool);
|
||||
BrushChannel *ch;
|
||||
|
||||
for (ch = (BrushChannel *)br->channels->channels.first; ch; ch = ch->next) {
|
||||
BrushChannelType *def = ch->def;
|
||||
|
||||
BKE_brush_channel_free_data(ch);
|
||||
BKE_brush_channel_init(ch, def);
|
||||
}
|
||||
|
||||
brush_defaults(br);
|
||||
BKE_brush_curve_preset(br, CURVE_PRESET_SMOOTH);
|
||||
BKE_brush_default_input_curves_set(br);
|
||||
|
||||
/* Use the curve presets by default */
|
||||
br->curve_preset = BRUSH_CURVE_SMOOTH;
|
||||
@@ -1703,10 +1819,17 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
* assign this so logic below can remain the same. */
|
||||
br->alpha = 0.5f;
|
||||
|
||||
bool disable_dyntopo = false;
|
||||
|
||||
// XXX basic face set setup for all organic brushes
|
||||
br->autosmooth_fset_slide = 1.0f;
|
||||
br->flag2 |= BRUSH_SMOOTH_PRESERVE_FACE_SETS | BRUSH_SMOOTH_USE_AREA_WEIGHT;
|
||||
|
||||
/* Brush settings */
|
||||
switch (br->sculpt_tool) {
|
||||
case SCULPT_TOOL_DRAW_SHARP:
|
||||
br->flag |= BRUSH_DIR_IN;
|
||||
br->flag |= BRUSH_SIZE_PRESSURE;
|
||||
br->curve_preset = BRUSH_CURVE_POW4;
|
||||
br->spacing = 5;
|
||||
break;
|
||||
@@ -1714,11 +1837,28 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
br->curve_preset = BRUSH_CURVE_SMOOTHER;
|
||||
br->spacing = 10;
|
||||
br->alpha = 1.0f;
|
||||
|
||||
disable_dyntopo = true;
|
||||
|
||||
break;
|
||||
case SCULPT_TOOL_FAIRING:
|
||||
br->curve_preset = BRUSH_CURVE_SMOOTHER;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
br->spacing = 10;
|
||||
br->alpha = 1.0f;
|
||||
break;
|
||||
case SCULPT_TOOL_SCENE_PROJECT:
|
||||
br->curve_preset = BRUSH_CURVE_SMOOTHER;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
br->spacing = 10;
|
||||
br->alpha = 1.0f;
|
||||
break;
|
||||
case SCULPT_TOOL_SLIDE_RELAX:
|
||||
br->spacing = 10;
|
||||
br->alpha = 1.0f;
|
||||
br->slide_deform_type = BRUSH_SLIDE_DEFORM_DRAG;
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_CLAY:
|
||||
br->flag |= BRUSH_SIZE_PRESSURE;
|
||||
@@ -1735,15 +1875,36 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
br->flag |= BRUSH_SIZE_PRESSURE;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
break;
|
||||
case SCULPT_TOOL_CLAY_STRIPS:
|
||||
case SCULPT_TOOL_TWIST:
|
||||
br->alpha = 0.5f;
|
||||
br->normal_radius_factor = 1.0f;
|
||||
br->spacing = 6;
|
||||
br->hardness = 0.5f;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
br->flag &= ~BRUSH_SIZE_PRESSURE;
|
||||
break;
|
||||
case SCULPT_TOOL_CLAY_STRIPS: {
|
||||
br->flag |= BRUSH_ACCUMULATE | BRUSH_SIZE_PRESSURE;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
br->alpha = 0.6f;
|
||||
br->spacing = 5;
|
||||
br->normal_radius_factor = 1.55f;
|
||||
br->alpha = 0.8f;
|
||||
br->spacing = 7;
|
||||
br->normal_radius_factor = 1.35f;
|
||||
br->tip_roundness = 0.18f;
|
||||
br->curve_preset = BRUSH_CURVE_SMOOTHER;
|
||||
break;
|
||||
|
||||
CurveMap *cuma = br->pressure_size_curve->cm;
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.55f;
|
||||
BKE_curvemap_insert(cuma, 0.5f, 0.7f);
|
||||
cuma->curve[2].x = 1.0f;
|
||||
cuma->curve[2].y = 1.0f;
|
||||
BKE_curvemapping_changed(br->pressure_size_curve, true);
|
||||
|
||||
cuma = br->pressure_strength_curve->cm;
|
||||
BKE_curvemap_insert(cuma, 0.6f, 0.25f);
|
||||
BKE_curvemapping_changed(br->pressure_strength_curve, true);
|
||||
|
||||
} break;
|
||||
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
|
||||
br->flag2 |= BRUSH_MULTIPLANE_SCRAPE_DYNAMIC | BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW;
|
||||
br->alpha = 0.7f;
|
||||
@@ -1766,18 +1927,29 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
break;
|
||||
case SCULPT_TOOL_ROTATE:
|
||||
br->alpha = 1.0;
|
||||
disable_dyntopo = true;
|
||||
|
||||
break;
|
||||
case SCULPT_TOOL_SMOOTH:
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
br->flag2 |= BRUSH_SMOOTH_PRESERVE_FACE_SETS | BRUSH_SMOOTH_USE_AREA_WEIGHT;
|
||||
|
||||
br->spacing = 5;
|
||||
br->alpha = 0.7f;
|
||||
br->surface_smooth_shape_preservation = 0.5f;
|
||||
br->surface_smooth_current_vertex = 0.5f;
|
||||
br->surface_smooth_iterations = 4;
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_SNAKE_HOOK:
|
||||
br->alpha = 1.0f;
|
||||
br->rake_factor = 1.0f;
|
||||
br->dyntopo.inherit = DYNTOPO_INHERIT_BITMASK &
|
||||
~(DYNTOPO_INHERIT_ALL | DYNTOPO_LOCAL_COLLAPSE |
|
||||
DYNTOPO_INHERIT_DETAIL_RANGE);
|
||||
br->dyntopo.flag |= DYNTOPO_LOCAL_COLLAPSE;
|
||||
br->dyntopo.detail_range = 0.4f;
|
||||
break;
|
||||
case SCULPT_TOOL_THUMB:
|
||||
br->size = 75;
|
||||
@@ -1791,6 +1963,8 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
br->flag &= ~BRUSH_ALPHA_PRESSURE;
|
||||
br->flag &= ~BRUSH_SPACE;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_POSE:
|
||||
br->pose_smooth_iterations = 4;
|
||||
@@ -1799,18 +1973,24 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
br->flag &= ~BRUSH_ALPHA_PRESSURE;
|
||||
br->flag &= ~BRUSH_SPACE;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_BOUNDARY:
|
||||
br->flag &= ~BRUSH_ALPHA_PRESSURE;
|
||||
br->flag &= ~BRUSH_SPACE;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
br->curve_preset = BRUSH_CURVE_CONSTANT;
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_DRAW_FACE_SETS:
|
||||
br->alpha = 0.5f;
|
||||
br->flag &= ~BRUSH_ALPHA_PRESSURE;
|
||||
br->flag &= ~BRUSH_SPACE;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_GRAB:
|
||||
br->alpha = 0.4f;
|
||||
@@ -1818,6 +1998,8 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
br->flag &= ~BRUSH_ALPHA_PRESSURE;
|
||||
br->flag &= ~BRUSH_SPACE;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_CLOTH:
|
||||
br->cloth_mass = 1.0f;
|
||||
@@ -1826,6 +2008,8 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
br->cloth_sim_falloff = 0.75f;
|
||||
br->cloth_deform_type = BRUSH_CLOTH_DEFORM_DRAG;
|
||||
br->flag &= ~(BRUSH_ALPHA_PRESSURE | BRUSH_SIZE_PRESSURE);
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_LAYER:
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
@@ -1843,6 +2027,8 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
br->density = 1.0f;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
zero_v3(br->rgb);
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_SMEAR:
|
||||
br->alpha = 1.0f;
|
||||
@@ -1850,6 +2036,18 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
br->flag &= ~BRUSH_ALPHA_PRESSURE;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
br->curve_preset = BRUSH_CURVE_SPHERE;
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_VCOL_BOUNDARY:
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
br->spacing = 5;
|
||||
br->alpha = 0.7f;
|
||||
br->surface_smooth_shape_preservation = 0.5f;
|
||||
br->surface_smooth_current_vertex = 0.5f;
|
||||
br->surface_smooth_iterations = 4;
|
||||
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
case SCULPT_TOOL_DISPLACEMENT_SMEAR:
|
||||
br->alpha = 1.0f;
|
||||
@@ -1858,11 +2056,17 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
br->flag &= ~BRUSH_ALPHA_PRESSURE;
|
||||
br->flag &= ~BRUSH_SPACE_ATTEN;
|
||||
br->curve_preset = BRUSH_CURVE_SMOOTHER;
|
||||
disable_dyntopo = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (disable_dyntopo) {
|
||||
// disabled flag is never inherited
|
||||
br->dyntopo.flag |= DYNTOPO_DISABLED;
|
||||
}
|
||||
|
||||
/* Cursor colors */
|
||||
|
||||
/* Default Alpha */
|
||||
@@ -1910,6 +2114,7 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
case SCULPT_TOOL_POSE:
|
||||
case SCULPT_TOOL_BOUNDARY:
|
||||
case SCULPT_TOOL_SLIDE_RELAX:
|
||||
case SCULPT_TOOL_TWIST:
|
||||
br->add_col[0] = 1.0f;
|
||||
br->add_col[1] = 0.95f;
|
||||
br->add_col[2] = 0.005f;
|
||||
@@ -1919,11 +2124,26 @@ void BKE_brush_sculpt_reset(Brush *br)
|
||||
break;
|
||||
|
||||
case SCULPT_TOOL_SIMPLIFY:
|
||||
// don't use DYNTOPO_INHERIT_BITMASK, we want to include
|
||||
// future bits
|
||||
|
||||
br->flag2 |= BRUSH_SMOOTH_PRESERVE_FACE_SETS | BRUSH_SMOOTH_USE_AREA_WEIGHT |
|
||||
BRUSH_CURVATURE_RAKE;
|
||||
br->dyntopo.inherit = 0x7FFFFFFF &
|
||||
~(DYNTOPO_INHERIT_ALL | DYNTOPO_SUBDIVIDE | DYNTOPO_COLLAPSE);
|
||||
br->dyntopo.flag |= DYNTOPO_COLLAPSE | DYNTOPO_SUBDIVIDE;
|
||||
br->autosmooth_factor = 0.05;
|
||||
br->topology_rake_factor = 0.35;
|
||||
br->topology_rake_projection = 0.975;
|
||||
|
||||
break;
|
||||
case SCULPT_TOOL_VCOL_BOUNDARY:
|
||||
case SCULPT_TOOL_PAINT:
|
||||
case SCULPT_TOOL_MASK:
|
||||
case SCULPT_TOOL_DRAW_FACE_SETS:
|
||||
case SCULPT_TOOL_DISPLACEMENT_ERASER:
|
||||
case SCULPT_TOOL_DISPLACEMENT_SMEAR:
|
||||
case SCULPT_TOOL_ARRAY:
|
||||
br->add_col[0] = 0.75f;
|
||||
br->add_col[1] = 0.75f;
|
||||
br->add_col[2] = 0.75f;
|
||||
@@ -2041,7 +2261,7 @@ float BKE_brush_sample_tex_3d(const Scene *scene,
|
||||
/* leave the coordinates relative to the screen */
|
||||
|
||||
/* use unadjusted size for tiled mode */
|
||||
invradius = 1.0f / BKE_brush_size_get(scene, br);
|
||||
invradius = 1.0f / BKE_brush_size_get(scene, br, false);
|
||||
|
||||
x = point_2d[0];
|
||||
y = point_2d[1];
|
||||
@@ -2154,7 +2374,7 @@ float BKE_brush_sample_masktex(
|
||||
/* leave the coordinates relative to the screen */
|
||||
|
||||
/* use unadjusted size for tiled mode */
|
||||
invradius = 1.0f / BKE_brush_size_get(scene, br);
|
||||
invradius = 1.0f / BKE_brush_size_get(scene, br, false);
|
||||
|
||||
x = point_2d[0];
|
||||
y = point_2d[1];
|
||||
@@ -2244,8 +2464,19 @@ void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float c
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
|
||||
void BKE_brush_size_set(Scene *scene, Brush *brush, int size, bool use_brush_channels)
|
||||
{
|
||||
if (use_brush_channels) {
|
||||
if (scene->toolsettings->sculpt && scene->toolsettings->sculpt->channels) {
|
||||
BKE_brush_channelset_set_final_float(
|
||||
brush->channels, scene->toolsettings->sculpt->channels, "radius", (float)size);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
BKE_brush_channelset_set_float(brush->channels, "radius", (float)size);
|
||||
}
|
||||
}
|
||||
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
|
||||
/* make sure range is sane */
|
||||
@@ -2259,8 +2490,22 @@ void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
|
||||
}
|
||||
}
|
||||
|
||||
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
|
||||
int BKE_brush_size_get(const Scene *scene, const Brush *brush, bool use_brush_channel)
|
||||
{
|
||||
if (!scene->toolsettings->sculpt || !scene->toolsettings->sculpt->channels || !brush->channels) {
|
||||
use_brush_channel = false;
|
||||
}
|
||||
|
||||
if (use_brush_channel) {
|
||||
if (scene->toolsettings->sculpt) {
|
||||
return (int)BKE_brush_channelset_get_final_float(
|
||||
brush->channels, scene->toolsettings->sculpt->channels, "radius", NULL);
|
||||
}
|
||||
else {
|
||||
return (int)BKE_brush_channelset_get_float(brush->channels, "radius", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
|
||||
|
||||
@@ -2403,7 +2648,7 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
|
||||
spread = 1.0;
|
||||
}
|
||||
else {
|
||||
diameter = 2 * BKE_brush_size_get(scene, brush);
|
||||
diameter = 2 * BKE_brush_size_get(scene, brush, false);
|
||||
spread = brush->jitter;
|
||||
}
|
||||
/* find random position within a circle of diameter 1 */
|
||||
@@ -2426,7 +2671,7 @@ void BKE_brush_randomize_texture_coords(UnifiedPaintSettings *ups, bool mask)
|
||||
}
|
||||
|
||||
/* Uses the brush curve control to find a strength value */
|
||||
float BKE_brush_curve_strength(const Brush *br, float p, const float len)
|
||||
ATTR_NO_OPT float BKE_brush_curve_strength(const Brush *br, float p, const float len)
|
||||
{
|
||||
float strength = 1.0f;
|
||||
|
||||
@@ -2554,3 +2799,135 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool
|
||||
|
||||
return im;
|
||||
}
|
||||
|
||||
void BKE_brush_get_dyntopo(Brush *brush, Sculpt *sd, DynTopoSettings *out)
|
||||
{
|
||||
*out = brush->dyntopo;
|
||||
|
||||
int inherit = out->inherit;
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_ALL) {
|
||||
inherit = 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
if (!(sd->flags & SCULPT_DYNTOPO_ENABLED)) {
|
||||
out->flag |= DYNTOPO_DISABLED;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_MODE) {
|
||||
if (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT) {
|
||||
out->mode = DYNTOPO_DETAIL_CONSTANT;
|
||||
}
|
||||
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
|
||||
out->mode = DYNTOPO_DETAIL_BRUSH;
|
||||
}
|
||||
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL) {
|
||||
out->mode = DYNTOPO_DETAIL_MANUAL;
|
||||
}
|
||||
else {
|
||||
out->mode = DYNTOPO_DETAIL_RELATIVE;
|
||||
}
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_RADIUS_SCALE) {
|
||||
out->radius_scale = sd->dyntopo_radius_scale;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_DETAIL_SIZE) {
|
||||
out->detail_size = sd->detail_size;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_DETAIL_RANGE) {
|
||||
out->detail_range = sd->detail_range;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_DETAIL_PERCENT) {
|
||||
out->detail_percent = sd->detail_percent;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_SPACING) {
|
||||
out->spacing = sd->dyntopo_spacing;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_CONSTANT_DETAIL) {
|
||||
out->constant_detail = sd->constant_detail;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_SUBDIVIDE) {
|
||||
if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) {
|
||||
out->flag |= DYNTOPO_SUBDIVIDE;
|
||||
}
|
||||
else {
|
||||
out->flag &= ~DYNTOPO_SUBDIVIDE;
|
||||
}
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_LOCAL_COLLAPSE) {
|
||||
if (sd->flags & SCULPT_DYNTOPO_LOCAL_COLLAPSE) {
|
||||
out->flag |= DYNTOPO_LOCAL_COLLAPSE;
|
||||
}
|
||||
else {
|
||||
out->flag &= ~DYNTOPO_LOCAL_COLLAPSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_LOCAL_SUBDIVIDE) {
|
||||
if (sd->flags & SCULPT_DYNTOPO_LOCAL_SUBDIVIDE) {
|
||||
out->flag |= DYNTOPO_LOCAL_SUBDIVIDE;
|
||||
}
|
||||
else {
|
||||
out->flag &= ~DYNTOPO_LOCAL_SUBDIVIDE;
|
||||
}
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_COLLAPSE) {
|
||||
if (sd->flags & SCULPT_DYNTOPO_COLLAPSE) {
|
||||
out->flag |= DYNTOPO_COLLAPSE;
|
||||
}
|
||||
else {
|
||||
out->flag &= ~DYNTOPO_COLLAPSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_CLEANUP) {
|
||||
if (sd->flags & SCULPT_DYNTOPO_CLEANUP) {
|
||||
out->flag |= DYNTOPO_CLEANUP;
|
||||
}
|
||||
else {
|
||||
out->flag &= ~DYNTOPO_CLEANUP;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool BKE_brush_hard_edge_mode_get(const Scene *scene, const Brush *brush)
|
||||
{
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
bool ret = (ups->flag & UNIFIED_PAINT_FLAG_HARD_EDGE_MODE) ? ups->hard_edge_mode :
|
||||
brush->flag2 & BRUSH_HARD_EDGE_MODE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BKE_brush_hard_edge_mode_set(Scene *scene, Brush *brush, bool val)
|
||||
{
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
|
||||
if (ups->flag & UNIFIED_PAINT_FLAG_HARD_EDGE_MODE) {
|
||||
ups->hard_edge_mode = val;
|
||||
}
|
||||
else {
|
||||
if (val) {
|
||||
brush->flag2 |= BRUSH_HARD_EDGE_MODE;
|
||||
}
|
||||
else {
|
||||
brush->flag2 &= ~BRUSH_HARD_EDGE_MODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float BKE_brush_fset_slide_get(const Scene *scene, const Brush *brush)
|
||||
{
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
|
||||
return BKE_brush_hard_edge_mode_get(scene, brush) ? 0.0f : brush->autosmooth_fset_slide;
|
||||
}
|
||||
|
1589
source/blender/blenkernel/intern/brush_engine.c
Normal file
1589
source/blender/blenkernel/intern/brush_engine.c
Normal file
File diff suppressed because it is too large
Load Diff
1179
source/blender/blenkernel/intern/brush_engine_presets.c
Normal file
1179
source/blender/blenkernel/intern/brush_engine_presets.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -171,8 +171,16 @@ static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
|
||||
if (!cddm->pmap && ob->type == OB_MESH) {
|
||||
Mesh *me = ob->data;
|
||||
|
||||
BKE_mesh_vert_poly_map_create(
|
||||
&cddm->pmap, &cddm->pmap_mem, me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
|
||||
BKE_mesh_vert_poly_map_create(&cddm->pmap,
|
||||
&cddm->pmap_mem,
|
||||
me->mvert,
|
||||
me->medge,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->totvert,
|
||||
me->totpoly,
|
||||
me->totloop,
|
||||
false);
|
||||
}
|
||||
|
||||
return cddm->pmap;
|
||||
|
@@ -688,9 +688,12 @@ static Collection *collection_duplicate_recursive(Main *bmain,
|
||||
Collection *BKE_collection_duplicate(Main *bmain,
|
||||
Collection *parent,
|
||||
Collection *collection,
|
||||
eDupli_ID_Flags duplicate_flags,
|
||||
eLibIDDuplicateFlags duplicate_options)
|
||||
const uint duplicate_flags_in, // it's not const!! - joeedh
|
||||
const uint duplicate_options_in) // not const!
|
||||
{
|
||||
uint duplicate_flags = duplicate_flags_in;
|
||||
uint duplicate_options = duplicate_options_in;
|
||||
|
||||
const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
|
||||
const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
|
||||
|
||||
|
@@ -85,7 +85,8 @@ void BKE_curvemapping_set_defaults(
|
||||
cumap->changed_timestamp = 0;
|
||||
}
|
||||
|
||||
CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
|
||||
ATTR_NO_OPT CurveMapping *BKE_curvemapping_add(
|
||||
int tot, float minx, float miny, float maxx, float maxy)
|
||||
{
|
||||
CurveMapping *cumap;
|
||||
|
||||
@@ -96,7 +97,7 @@ CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx,
|
||||
return cumap;
|
||||
}
|
||||
|
||||
void BKE_curvemapping_free_data(CurveMapping *cumap)
|
||||
ATTR_NO_OPT void BKE_curvemapping_free_data(CurveMapping *cumap)
|
||||
{
|
||||
int a;
|
||||
|
||||
@@ -124,12 +125,57 @@ void BKE_curvemapping_free(CurveMapping *cumap)
|
||||
}
|
||||
}
|
||||
|
||||
static void *my_dupalloc_id(void *mem, const char *tag)
|
||||
{
|
||||
size_t size = MEM_allocN_len(mem);
|
||||
|
||||
void *ret = MEM_mallocN(size, tag);
|
||||
memcpy(ret, mem, size);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
void BKE_curvemapping_copy_data_tag_ex(CurveMapping *target,
|
||||
const CurveMapping *cumap,
|
||||
const char *tag)
|
||||
{
|
||||
int a;
|
||||
|
||||
bool not_cache = !(target->flag & CUMA_PART_OF_CACHE);
|
||||
|
||||
*target = *cumap;
|
||||
|
||||
if (not_cache) {
|
||||
target->flag &= ~CUMA_PART_OF_CACHE;
|
||||
}
|
||||
|
||||
target->cache_users = 0;
|
||||
|
||||
for (a = 0; a < CM_TOT; a++) {
|
||||
if (cumap->cm[a].curve) {
|
||||
target->cm[a].curve = my_dupalloc_id(cumap->cm[a].curve, tag);
|
||||
}
|
||||
if (cumap->cm[a].table) {
|
||||
target->cm[a].table = my_dupalloc_id(cumap->cm[a].table, tag);
|
||||
}
|
||||
if (cumap->cm[a].premultable) {
|
||||
target->cm[a].premultable = my_dupalloc_id(cumap->cm[a].premultable, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
|
||||
{
|
||||
int a;
|
||||
|
||||
bool not_cache = !(target->flag & CUMA_PART_OF_CACHE);
|
||||
|
||||
*target = *cumap;
|
||||
|
||||
if (not_cache) {
|
||||
target->flag &= ~CUMA_PART_OF_CACHE;
|
||||
}
|
||||
|
||||
for (a = 0; a < CM_TOT; a++) {
|
||||
if (cumap->cm[a].curve) {
|
||||
target->cm[a].curve = MEM_dupallocN(cumap->cm[a].curve);
|
||||
@@ -143,11 +189,12 @@ void BKE_curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
|
||||
}
|
||||
}
|
||||
|
||||
CurveMapping *BKE_curvemapping_copy(const CurveMapping *cumap)
|
||||
ATTR_NO_OPT CurveMapping *BKE_curvemapping_copy(const CurveMapping *cumap)
|
||||
{
|
||||
if (cumap) {
|
||||
CurveMapping *cumapn = MEM_dupallocN(cumap);
|
||||
BKE_curvemapping_copy_data(cumapn, cumap);
|
||||
cumapn->flag &= ~CUMA_PART_OF_CACHE;
|
||||
return cumapn;
|
||||
}
|
||||
return NULL;
|
||||
@@ -305,6 +352,15 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
|
||||
case CURVE_PRESET_BELL:
|
||||
cuma->totpoint = 3;
|
||||
break;
|
||||
case CURVE_PRESET_POW2:
|
||||
cuma->totpoint = 5;
|
||||
break;
|
||||
case CURVE_PRESET_POW3:
|
||||
cuma->totpoint = 6;
|
||||
break;
|
||||
case CURVE_PRESET_POW15:
|
||||
cuma->totpoint = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
cuma->curve = MEM_callocN(cuma->totpoint * sizeof(CurveMapPoint), "curve points");
|
||||
@@ -401,8 +457,60 @@ void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope
|
||||
cuma->curve[2].x = 1.0f;
|
||||
cuma->curve[2].y = 0.025f;
|
||||
break;
|
||||
}
|
||||
case CURVE_PRESET_POW2:
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.0f;
|
||||
|
||||
cuma->curve[1].x = 0.25f;
|
||||
cuma->curve[1].y = 0.0625f;
|
||||
|
||||
cuma->curve[2].x = 0.5;
|
||||
cuma->curve[2].y = 0.25;
|
||||
|
||||
cuma->curve[3].x = 0.75f;
|
||||
cuma->curve[3].y = 0.5625f;
|
||||
|
||||
cuma->curve[4].x = 1.0f;
|
||||
cuma->curve[4].y = 1.0f;
|
||||
|
||||
case CURVE_PRESET_POW3:
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.0f;
|
||||
|
||||
cuma->curve[1].x = 0.135f;
|
||||
cuma->curve[1].y = 0.002f;
|
||||
|
||||
cuma->curve[2].x = 0.318;
|
||||
cuma->curve[2].y = 0.032;
|
||||
|
||||
cuma->curve[3].x = 0.528;
|
||||
cuma->curve[3].y = 0.147f;
|
||||
|
||||
cuma->curve[4].x = 0.757f;
|
||||
cuma->curve[4].y = 0.433f;
|
||||
|
||||
cuma->curve[5].x = 1.0f;
|
||||
cuma->curve[5].y = 1.0f;
|
||||
case CURVE_PRESET_POW15:
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.0f;
|
||||
|
||||
cuma->curve[1].x = 0.135f;
|
||||
cuma->curve[1].y = 0.002f;
|
||||
|
||||
cuma->curve[2].x = 0.318;
|
||||
cuma->curve[2].y = 0.032;
|
||||
|
||||
cuma->curve[3].x = 0.528;
|
||||
cuma->curve[3].y = 0.147f;
|
||||
|
||||
cuma->curve[4].x = 0.757f;
|
||||
cuma->curve[4].y = 0.433f;
|
||||
|
||||
cuma->curve[5].x = 1.0f;
|
||||
cuma->curve[5].y = 1.0f;
|
||||
}
|
||||
//[[0,0], [0.134,0.002], [0.318,0.032], [0.528,0.147], [0.757,0.433], [1,1]
|
||||
/* mirror curve in x direction to have positive slope
|
||||
* rather than default negative slope */
|
||||
if (slope == CURVEMAP_SLOPE_POSITIVE) {
|
||||
@@ -1241,7 +1349,8 @@ void BKE_curvemapping_blend_write(BlendWriter *writer, const CurveMapping *cumap
|
||||
BKE_curvemapping_curves_blend_write(writer, cumap);
|
||||
}
|
||||
|
||||
void BKE_curvemapping_curves_blend_write(BlendWriter *writer, const CurveMapping *cumap)
|
||||
ATTR_NO_OPT void BKE_curvemapping_curves_blend_write(BlendWriter *writer,
|
||||
const CurveMapping *cumap)
|
||||
{
|
||||
for (int a = 0; a < CM_TOT; a++) {
|
||||
BLO_write_struct_array(writer, CurveMapPoint, cumap->cm[a].totpoint, cumap->cm[a].curve);
|
||||
@@ -1252,7 +1361,7 @@ void BKE_curvemapping_curves_blend_write(BlendWriter *writer, const CurveMapping
|
||||
void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
|
||||
{
|
||||
/* flag seems to be able to hang? Maybe old files... not bad to clear anyway */
|
||||
cumap->flag &= ~CUMA_PREMULLED;
|
||||
cumap->flag &= ~(CUMA_PREMULLED | CUMA_PART_OF_CACHE);
|
||||
|
||||
for (int a = 0; a < CM_TOT; a++) {
|
||||
BLO_read_data_address(reader, &cumap->cm[a].curve);
|
||||
|
@@ -351,7 +351,10 @@ static void crazyspace_init_verts_and_matrices(const Mesh *mesh,
|
||||
|
||||
static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md)
|
||||
{
|
||||
if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
|
||||
if (md->type == eModifierType_Multires) {
|
||||
return true;
|
||||
}
|
||||
if (md->type == eModifierType_Subsurf && md->mode & eModifierMode_OnCage) {
|
||||
return true;
|
||||
}
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
|
||||
|
@@ -100,7 +100,7 @@ static void curve_bevel_make_extrude_and_fill(const Curve *cu,
|
||||
* for #Curve.bevresol is 32. */
|
||||
float *quarter_coords_x = alloca(sizeof(float) * (cu->bevresol + 1));
|
||||
float *quarter_coords_y = alloca(sizeof(float) * (cu->bevresol + 1));
|
||||
bevel_quarter_fill(cu, quarter_coords_x, quarter_coords_y);
|
||||
bevel_quarter_fill((Curve *)cu, quarter_coords_x, quarter_coords_y);
|
||||
|
||||
int nr;
|
||||
if (fill_type == FULL) {
|
||||
|
318
source/blender/blenkernel/intern/curvemapping_cache.c
Normal file
318
source/blender/blenkernel/intern/curvemapping_cache.c
Normal file
@@ -0,0 +1,318 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_alloca.h"
|
||||
#include "BLI_array.h"
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_hash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_mempool.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_smallhash.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_brush_enums.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_color_types.h"
|
||||
#include "DNA_curveprofile_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_sculpt_brush_types.h"
|
||||
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_colorband.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_paint.h"
|
||||
|
||||
#include "BKE_brush_engine.h"
|
||||
#include "BKE_curvemapping_cache.h"
|
||||
#include "BKE_curveprofile.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
/*
|
||||
The brush system needs to make lots of copies of BrushChannels
|
||||
as it resolves relationships between commands, brushes and the tool settings.
|
||||
|
||||
Unfortunately each brush command has five parameter curves, and copying
|
||||
them over and over again has proven to be slow.
|
||||
|
||||
Solution: a kind of small string optimization approach but for curves
|
||||
*/
|
||||
|
||||
static int curvmapping_curve_count(const CurveMapping *cumap)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < CM_TOT; i++) {
|
||||
if (cumap->cm[i].curve) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT bool BKE_curvemapping_equals(const CurveMapping *a, const CurveMapping *b)
|
||||
{
|
||||
int count = curvmapping_curve_count(a);
|
||||
|
||||
if (curvmapping_curve_count(b) != count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
|
||||
ok = ok && a->tone == b->tone;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ok = ok && a->black[i] == b->black[i];
|
||||
ok = ok && a->white[i] == b->white[i];
|
||||
ok = ok && a->bwmul[i] == b->bwmul[i];
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
const CurveMap *c1 = a->cm + i;
|
||||
const CurveMap *c2 = b->cm + i;
|
||||
|
||||
if (!c1 || !c2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c1->totpoint != c2->totpoint) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int j = 0; j < c1->totpoint; j++) {
|
||||
ok = ok && fabsf(c1->curve[j].x - c2->curve[j].x) <= FLT_EPSILON * 8;
|
||||
ok = ok && fabsf(c1->curve[j].y - c2->curve[j].y) <= FLT_EPSILON * 8;
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*truncate float to avoid rounding errors
|
||||
messing up the hash*/
|
||||
#define FRACT_TRUNCATE_STEPS 8192.0f
|
||||
ATTR_NO_OPT BLI_INLINE unsigned int get_float_hash(float f)
|
||||
{
|
||||
float f_floor = floor(f);
|
||||
float fract = f - f_floor;
|
||||
|
||||
fract = floorf(fract * FRACT_TRUNCATE_STEPS) / FRACT_TRUNCATE_STEPS;
|
||||
|
||||
uint *ret = (uint *)&f;
|
||||
return *ret;
|
||||
}
|
||||
|
||||
#define HASHFLOAT(f) h = get_float_hash(f), hash ^= BLI_hash_int(h + hi++)
|
||||
#define HASHINT(f) h = get_float_hash(f), hash ^= BLI_hash_int(f + hi++)
|
||||
|
||||
ATTR_NO_OPT uint BKE_curvemapping_calc_hash(const CurveMapping *cumap)
|
||||
{
|
||||
uint hash = 0;
|
||||
uint h = 0;
|
||||
uint hi = 0;
|
||||
int totcurve = curvmapping_curve_count(cumap);
|
||||
|
||||
HASHINT(totcurve);
|
||||
HASHINT(cumap->tone);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
HASHFLOAT(cumap->white[i]);
|
||||
HASHFLOAT(cumap->black[i]);
|
||||
HASHFLOAT(cumap->bwmul[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < totcurve; i++) {
|
||||
if (!cumap->cm[i].curve) {
|
||||
break;
|
||||
}
|
||||
|
||||
const CurveMap *cu = cumap->cm + i;
|
||||
|
||||
for (int j = 0; j < cu->totpoint; j++) {
|
||||
HASHFLOAT(cu->curve[j].x);
|
||||
HASHFLOAT(cu->curve[j].y);
|
||||
}
|
||||
}
|
||||
|
||||
return hash & ((1 << 29) - 1);
|
||||
}
|
||||
|
||||
static bool curves_equals(const void *a, const void *b)
|
||||
{
|
||||
// ghash requires we invert here
|
||||
|
||||
return !BKE_curvemapping_equals(a, b);
|
||||
}
|
||||
|
||||
static unsigned int curve_hash(const void *c)
|
||||
{
|
||||
return BKE_curvemapping_calc_hash(c);
|
||||
}
|
||||
|
||||
CurveMappingCache *BKE_curvemapping_cache_create()
|
||||
{
|
||||
CurveMappingCache *ret = MEM_callocN(sizeof(*ret), "CurveMappingCache");
|
||||
|
||||
ret->gh = BLI_ghash_new(curve_hash, curves_equals, "CurveMappingCache ghash");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BKE_curvemapping_cache_aquire(CurveMappingCache *cache, CurveMapping *curve)
|
||||
{
|
||||
curve->cache_users++;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_curvemapping_cache_release(CurveMappingCache *cache, CurveMapping *curve)
|
||||
{
|
||||
curve->cache_users--;
|
||||
|
||||
if ((curve->flag & CUMA_PART_OF_CACHE) && curve->cache_users < 0) {
|
||||
if (!BLI_ghash_remove(cache->gh, curve, NULL, NULL)) {
|
||||
printf("error, curve was not in cache! %p\n", curve);
|
||||
}
|
||||
|
||||
BKE_curvemapping_free(curve);
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_curvemapping_in_cache(CurveMapping *curve)
|
||||
{
|
||||
return curve->flag & CUMA_PART_OF_CACHE;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT CurveMapping *BKE_curvemapping_cache_get(CurveMappingCache *cache,
|
||||
CurveMapping *curve,
|
||||
bool free_input)
|
||||
{
|
||||
void **key, **val;
|
||||
|
||||
CurveMapping *lookup;
|
||||
|
||||
if (BLI_ghash_ensure_p_ex(cache->gh, curve, &key, &val)) {
|
||||
lookup = *key;
|
||||
|
||||
if (free_input && lookup != curve && !(curve->flag & CUMA_PART_OF_CACHE)) {
|
||||
BKE_curvemapping_free(curve);
|
||||
}
|
||||
|
||||
lookup->cache_users++;
|
||||
|
||||
return lookup;
|
||||
}
|
||||
|
||||
printf("adding curve key %d\n", BKE_curvemapping_calc_hash(curve));
|
||||
|
||||
CurveMapping *curve2 = BKE_curvemapping_copy(curve);
|
||||
|
||||
*key = curve2;
|
||||
*val = curve2;
|
||||
|
||||
curve2->flag |= CUMA_PART_OF_CACHE;
|
||||
#if 1
|
||||
printf("%d %d",
|
||||
(int)BKE_curvemapping_calc_hash(curve2),
|
||||
(int)BKE_curvemapping_equals(curve, curve2));
|
||||
|
||||
CurveMap *cu = curve2->cm;
|
||||
printf("{\n");
|
||||
|
||||
for (int i = 0; i < cu->totpoint; i++) {
|
||||
printf(" %f, %f\n", cu->curve[i].x, cu->curve[i].y);
|
||||
}
|
||||
printf("}\n");
|
||||
#endif
|
||||
if (free_input && !(curve->flag & CUMA_PART_OF_CACHE)) {
|
||||
BKE_curvemapping_free(curve);
|
||||
}
|
||||
|
||||
curve2->cache_users = 1;
|
||||
|
||||
return curve2;
|
||||
}
|
||||
|
||||
void BKE_curvemapping_cache_free(CurveMappingCache *cache)
|
||||
{
|
||||
GHashIterator gi;
|
||||
|
||||
GHASH_ITER (gi, cache->gh) {
|
||||
CurveMapping *curve = BLI_ghashIterator_getKey(&gi);
|
||||
BKE_curvemapping_free(curve);
|
||||
}
|
||||
|
||||
BLI_ghash_free(cache->gh, NULL, NULL);
|
||||
MEM_freeN(cache);
|
||||
}
|
||||
|
||||
static CurveMappingCache *the_global_cache = NULL;
|
||||
|
||||
void BKE_curvemapping_cache_exit()
|
||||
{
|
||||
if (the_global_cache) {
|
||||
BKE_curvemapping_cache_free(the_global_cache);
|
||||
}
|
||||
}
|
||||
|
||||
CurveMappingCache *BKE_curvemapping_cache_global()
|
||||
{
|
||||
if (!the_global_cache) {
|
||||
the_global_cache = BKE_curvemapping_cache_create();
|
||||
}
|
||||
|
||||
return the_global_cache;
|
||||
}
|
||||
|
||||
// releases a curve if it's in the cache, otherwise frees it
|
||||
ATTR_NO_OPT void BKE_curvemapping_cache_release_or_free(CurveMappingCache *cache,
|
||||
CurveMapping *curve)
|
||||
{
|
||||
if (curve->flag & CUMA_PART_OF_CACHE) {
|
||||
BKE_curvemapping_cache_release(cache, curve);
|
||||
}
|
||||
else {
|
||||
BKE_curvemapping_free(curve);
|
||||
}
|
||||
|
||||
#if 0
|
||||
CurveMap *cu1 = curve->cm;
|
||||
CurveMap *cu2 = curve->cm;
|
||||
|
||||
if (cu1->totpoint != cu2->totpoint) {
|
||||
printf("%s: curvemapping cache error; totpoint differed: %d %d\n",
|
||||
__func__,
|
||||
cu1->totpoint,
|
||||
cu2->totpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("curve tables: {\n");
|
||||
|
||||
for (int i = 0; i < cu1->totpoint; i++) {
|
||||
CurveMapPoint *p1 = cu1->curve + i;
|
||||
CurveMapPoint *p2 = cu1->curve + i;
|
||||
printf(" %f, %f, | %f, %f\n", p1->x, p1->y, p2->x, p2->y);
|
||||
}
|
||||
printf("}\n");
|
||||
#endif
|
||||
}
|
@@ -35,6 +35,7 @@
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_endian_switch.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_color_blend.h"
|
||||
@@ -73,6 +74,32 @@ BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)NULL)->typemap) == CD_NUMTYPES, "siz
|
||||
|
||||
static CLG_LogRef LOG = {"bke.customdata"};
|
||||
|
||||
bool CustomData_layout_is_same(const CustomData *_a, const CustomData *_b)
|
||||
{
|
||||
CustomData a = *_a;
|
||||
CustomData b = *_b;
|
||||
|
||||
a.layers = b.layers = NULL;
|
||||
a.pool = b.pool = NULL;
|
||||
|
||||
if (memcmp((void *)&a, (void *)&b, sizeof(CustomData)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < a.totlayer; i++) {
|
||||
CustomDataLayer cla = _a->layers[i];
|
||||
CustomDataLayer clb = _b->layers[i];
|
||||
|
||||
cla.data = clb.data = NULL;
|
||||
|
||||
if (memcmp((void *)&cla, (void *)&clb, sizeof(CustomDataLayer)) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Update mask_dst with layers defined in mask_src (equivalent to a bitwise OR). */
|
||||
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst,
|
||||
const CustomData_MeshMasks *mask_src)
|
||||
@@ -1475,6 +1502,93 @@ static bool layerValidate_propfloat2(void *data, const uint totitems, const bool
|
||||
return has_errors;
|
||||
}
|
||||
|
||||
static void layerDynTopoVert_copy(const void *source, void *dest, int count)
|
||||
{
|
||||
const MDynTopoVert *mv = (MDynTopoVert *)dest;
|
||||
|
||||
memcpy(dest, source, count * sizeof(MDynTopoVert));
|
||||
}
|
||||
|
||||
static void layerDynTopoVert_interp(
|
||||
const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
|
||||
{
|
||||
float co[3], no[3], origmask, color[4];
|
||||
MDynTopoVert *mv = (MDynTopoVert *)dest;
|
||||
float totweight = 0.0f;
|
||||
|
||||
if (count == 0) {
|
||||
memset(mv, 0, sizeof(*mv));
|
||||
return;
|
||||
}
|
||||
|
||||
zero_v3(co);
|
||||
zero_v3(no);
|
||||
origmask = 0.0f;
|
||||
zero_v4(color);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
MDynTopoVert *mv2 = (MDynTopoVert *)sources[i];
|
||||
float w;
|
||||
|
||||
if (i == 0) { // copy flag from first source
|
||||
mv->flag = mv2->flag;
|
||||
mv->stroke_id = mv2->stroke_id;
|
||||
}
|
||||
|
||||
if (sub_weights) {
|
||||
w = sub_weights[i];
|
||||
}
|
||||
else {
|
||||
w = 1.0f;
|
||||
}
|
||||
|
||||
madd_v3_v3fl(co, mv2->origco, w);
|
||||
madd_v3_v3fl(no, mv2->origno, w);
|
||||
madd_v4_v4fl(color, mv2->origcolor, w);
|
||||
origmask += mv2->origmask * w;
|
||||
|
||||
totweight += w;
|
||||
}
|
||||
|
||||
float mul = 1.0f / totweight;
|
||||
|
||||
mul_v3_fl(co, mul);
|
||||
normalize_v3(no);
|
||||
|
||||
mul_v4_fl(color, mul);
|
||||
origmask *= mul;
|
||||
|
||||
copy_v3_v3(mv->origco, co);
|
||||
copy_v3_v3(mv->origno, no);
|
||||
copy_v4_v4(mv->origcolor, color);
|
||||
|
||||
mv->origmask = origmask;
|
||||
}
|
||||
|
||||
static void layerCopy_noop(const void *UNUSED(source), void *UNUSED(dest), int UNUSED(count))
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
static void layerInterp_noop(const void **UNUSED(sources),
|
||||
const float *UNUSED(weights),
|
||||
const float *UNUSED(sub_weights),
|
||||
int UNUSED(count),
|
||||
void *UNUSED(dest))
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
static void layerDefault_mesh_id(void *data, int count)
|
||||
{
|
||||
int *val = (int *)data;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
// val[i] = -1;
|
||||
val[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||
/* 0: CD_MVERT */
|
||||
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
@@ -1856,7 +1970,24 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL},
|
||||
};
|
||||
/* 51 CD_DYNTOPO_VERT */
|
||||
{sizeof(MDynTopoVert),
|
||||
"MDynTopoVert",
|
||||
1,
|
||||
NULL, // flag singleton layer
|
||||
layerDynTopoVert_copy,
|
||||
NULL,
|
||||
layerDynTopoVert_interp},
|
||||
/*52 CD_MESH_ID */
|
||||
{sizeof(unsigned int),
|
||||
"MIntProperty",
|
||||
1,
|
||||
NULL, // flag singleton layer
|
||||
layerCopy_propInt,
|
||||
NULL,
|
||||
layerInterp_noop,
|
||||
NULL,
|
||||
layerDefault_mesh_id}};
|
||||
|
||||
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
|
||||
/* 0-4 */ "CDMVert",
|
||||
@@ -1912,62 +2043,65 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
|
||||
"CDPropFloat3",
|
||||
"CDPropFloat2",
|
||||
"CDPropBoolean",
|
||||
};
|
||||
"CDDyntopoVert"};
|
||||
|
||||
const CustomData_MeshMasks CD_MASK_BAREMESH = {
|
||||
.vmask = CD_MASK_MVERT | CD_MASK_BWEIGHT,
|
||||
.emask = CD_MASK_MEDGE | CD_MASK_BWEIGHT,
|
||||
.vmask = CD_MASK_MVERT | CD_MASK_BWEIGHT | CD_MASK_MESH_ID,
|
||||
.emask = CD_MASK_MEDGE | CD_MASK_BWEIGHT | CD_MASK_MESH_ID,
|
||||
.fmask = 0,
|
||||
.lmask = CD_MASK_MLOOP,
|
||||
.pmask = CD_MASK_MPOLY | CD_MASK_FACEMAP,
|
||||
.lmask = CD_MASK_MLOOP | CD_MASK_MESH_ID,
|
||||
.pmask = CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_MESH_ID,
|
||||
};
|
||||
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
|
||||
.vmask = CD_MASK_MVERT | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX,
|
||||
.emask = CD_MASK_MEDGE | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX,
|
||||
.vmask = CD_MASK_MVERT | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX | CD_MASK_MESH_ID,
|
||||
.emask = CD_MASK_MEDGE | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX | CD_MASK_MESH_ID,
|
||||
.fmask = 0,
|
||||
.lmask = CD_MASK_MLOOP,
|
||||
.pmask = CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX,
|
||||
.lmask = CD_MASK_MLOOP | CD_MASK_MESH_ID,
|
||||
.pmask = CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX | CD_MASK_MESH_ID,
|
||||
};
|
||||
const CustomData_MeshMasks CD_MASK_MESH = {
|
||||
.vmask = (CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_PAINT_MASK |
|
||||
CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
|
||||
.emask = (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
|
||||
CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR | CD_MASK_MESH_ID),
|
||||
.emask = (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
|
||||
.fmask = 0,
|
||||
.lmask = (CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL |
|
||||
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
||||
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL |
|
||||
CD_MASK_MESH_ID),
|
||||
.pmask = (CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL |
|
||||
CD_MASK_SCULPT_FACE_SETS),
|
||||
CD_MASK_SCULPT_FACE_SETS | CD_MASK_MESH_ID),
|
||||
};
|
||||
const CustomData_MeshMasks CD_MASK_EDITMESH = {
|
||||
.vmask = (CD_MASK_MDEFORMVERT | CD_MASK_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
|
||||
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
|
||||
.emask = (CD_MASK_PROP_ALL),
|
||||
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR | CD_MASK_MESH_ID),
|
||||
.emask = (CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
|
||||
.fmask = 0,
|
||||
.lmask = (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
|
||||
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
||||
.pmask = (CD_MASK_FACEMAP | CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS),
|
||||
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
|
||||
.pmask = (CD_MASK_FACEMAP | CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS | CD_MASK_MESH_ID),
|
||||
};
|
||||
const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
|
||||
.vmask = (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN |
|
||||
CD_MASK_PAINT_MASK | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_PROP_ALL |
|
||||
CD_MASK_PROP_COLOR),
|
||||
.emask = (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
|
||||
CD_MASK_PROP_COLOR | CD_MASK_MESH_ID),
|
||||
.emask = (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
|
||||
.fmask = (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT),
|
||||
.lmask = (CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
|
||||
CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP |
|
||||
CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
|
||||
CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PROP_ALL |
|
||||
CD_MASK_MESH_ID), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
|
||||
.pmask = (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL |
|
||||
CD_MASK_SCULPT_FACE_SETS),
|
||||
CD_MASK_SCULPT_FACE_SETS | CD_MASK_MESH_ID),
|
||||
};
|
||||
const CustomData_MeshMasks CD_MASK_BMESH = {
|
||||
.vmask = (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
|
||||
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR),
|
||||
.emask = (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
|
||||
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR |
|
||||
CD_MASK_DYNTOPO_VERT | CD_MASK_MESH_ID),
|
||||
.emask = (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL |
|
||||
CD_MASK_MESH_ID),
|
||||
.fmask = 0,
|
||||
.lmask = (CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_CUSTOMLOOPNORMAL |
|
||||
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
|
||||
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_MESH_ID),
|
||||
.pmask = (CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL |
|
||||
CD_MASK_SCULPT_FACE_SETS),
|
||||
CD_MASK_SCULPT_FACE_SETS | CD_MASK_MESH_ID),
|
||||
};
|
||||
/**
|
||||
* cover values copied by #mesh_loops_to_tessdata
|
||||
@@ -2009,6 +2143,11 @@ static const LayerTypeInfo *layerType_getInfo(int type)
|
||||
return &LAYERTYPEINFO[type];
|
||||
}
|
||||
|
||||
int CustomData_get_elem_size(CustomDataLayer *layer)
|
||||
{
|
||||
return layerType_getInfo(layer->type)->size;
|
||||
}
|
||||
|
||||
static const char *layerType_getName(int type)
|
||||
{
|
||||
if (type < 0 || type >= CD_NUMTYPES) {
|
||||
@@ -2093,6 +2232,26 @@ static bool customdata_typemap_is_valid(const CustomData *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* copies all customdata layers without allocating data,
|
||||
* and without respect to type masks or NO_COPY/etc flags*/
|
||||
void CustomData_copy_all_layout(const struct CustomData *source, struct CustomData *dest)
|
||||
{
|
||||
*dest = *source;
|
||||
|
||||
if (dest->pool) {
|
||||
dest->pool = NULL;
|
||||
}
|
||||
|
||||
if (source->layers) {
|
||||
dest->layers = MEM_mallocN(sizeof(*dest->layers) * source->totlayer, __func__);
|
||||
|
||||
for (int i = 0; i < source->totlayer; i++) {
|
||||
dest->layers[i] = source->layers[i];
|
||||
dest->layers[i].data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CustomData_merge(const struct CustomData *source,
|
||||
struct CustomData *dest,
|
||||
CustomDataMask mask,
|
||||
@@ -2285,11 +2444,45 @@ static void customData_update_offsets(CustomData *data)
|
||||
const LayerTypeInfo *typeInfo;
|
||||
int offset = 0;
|
||||
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
typeInfo = layerType_getInfo(data->layers[i].type);
|
||||
// sort by alignment
|
||||
int aligns[] = {16, 8, 12, 6, 4, 2, 1};
|
||||
BLI_bitmap *donemap = BLI_BITMAP_NEW_ALLOCA(data->totlayer);
|
||||
|
||||
data->layers[i].offset = offset;
|
||||
offset += typeInfo->size;
|
||||
// do large structs first
|
||||
for (int j = 0; j < data->totlayer; j++) {
|
||||
typeInfo = layerType_getInfo(data->layers[j].type);
|
||||
if (typeInfo->size > 16 || typeInfo->size == 10) {
|
||||
int size = (int)typeInfo->size;
|
||||
|
||||
BLI_BITMAP_SET(donemap, j, true);
|
||||
|
||||
// align to 8-byte boundary
|
||||
if (size & 7) {
|
||||
size += 8 - (size & 7);
|
||||
}
|
||||
|
||||
data->layers[j].offset = offset;
|
||||
offset += size;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(aligns) + 1; i++) {
|
||||
for (int j = 0; j < data->totlayer; j++) {
|
||||
if (BLI_BITMAP_TEST(donemap, j)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
typeInfo = layerType_getInfo(data->layers[j].type);
|
||||
|
||||
if (i < ARRAY_SIZE(aligns) && typeInfo->size != aligns[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_BITMAP_SET(donemap, j, true);
|
||||
|
||||
data->layers[j].offset = offset;
|
||||
offset += typeInfo->size;
|
||||
}
|
||||
}
|
||||
|
||||
data->totsize = offset;
|
||||
@@ -2883,6 +3076,24 @@ bool CustomData_is_referenced_layer(struct CustomData *data, int type)
|
||||
return (layer->flag & CD_FLAG_NOFREE) != 0;
|
||||
}
|
||||
|
||||
void CustomData_unmark_temporary_nocopy(CustomData *data)
|
||||
{
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
if (data->layers[i].flag & CD_FLAG_TEMPORARY) {
|
||||
data->layers[i].flag &= ~CD_FLAG_NOCOPY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CustomData_mark_temporary_nocopy(CustomData *data)
|
||||
{
|
||||
for (int i = 0; i < data->totlayer; i++) {
|
||||
if (data->layers[i].flag & CD_FLAG_TEMPORARY) {
|
||||
data->layers[i].flag |= CD_FLAG_NOCOPY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CustomData_free_temporary(CustomData *data, int totelem)
|
||||
{
|
||||
int i, j;
|
||||
@@ -3739,6 +3950,12 @@ static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n
|
||||
int offset = data->layers[n].offset;
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
|
||||
|
||||
/* can't allow this to be called on CD_MESH_ID */
|
||||
|
||||
if (data->layers[n].type == CD_MESH_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeInfo->set_default) {
|
||||
typeInfo->set_default(POINTER_OFFSET(*block, offset), 1);
|
||||
}
|
||||
@@ -3758,6 +3975,95 @@ void CustomData_bmesh_set_default(CustomData *data, void **block)
|
||||
}
|
||||
}
|
||||
|
||||
void CustomData_bmesh_swap_data_simple(CustomData *data, void **block1, void **block2)
|
||||
{
|
||||
int cd_id = data->typemap[CD_MESH_ID];
|
||||
cd_id = cd_id >= 0 ? data->layers[cd_id].offset : -1;
|
||||
|
||||
void *tmp = *block1;
|
||||
*block1 = *block2;
|
||||
*block2 = tmp;
|
||||
|
||||
// unswap ids if they exist
|
||||
if (cd_id != -1 && *block1 && *block2) {
|
||||
int *id1 = (int *)(((char *)*block1) + cd_id);
|
||||
int *id2 = (int *)(((char *)*block2) + cd_id);
|
||||
|
||||
tmp = *id1;
|
||||
*id1 = *id2;
|
||||
*id2 = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void CustomData_bmesh_swap_data(CustomData *source,
|
||||
CustomData *dest,
|
||||
void *src_block,
|
||||
void **dest_block)
|
||||
{
|
||||
int src_i = 0;
|
||||
int dest_i = 0;
|
||||
int dest_i_start = 0;
|
||||
|
||||
if (*dest_block == NULL) {
|
||||
CustomData_bmesh_alloc_block(dest, dest_block);
|
||||
|
||||
if (*dest_block) {
|
||||
memset(*dest_block, 0, dest->totsize);
|
||||
CustomData_bmesh_set_default(dest, dest_block);
|
||||
}
|
||||
}
|
||||
|
||||
for (src_i = 0; src_i < source->totlayer; src_i++) {
|
||||
/* find the first dest layer with type >= the source type
|
||||
* (this should work because layers are ordered by type)
|
||||
*/
|
||||
while (dest_i_start < dest->totlayer &&
|
||||
dest->layers[dest_i_start].type < source->layers[src_i].type) {
|
||||
dest_i_start++;
|
||||
}
|
||||
|
||||
if (source->layers[src_i].type == CD_MESH_ID) {
|
||||
// do not swap ids
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if there are no more dest layers, we're done */
|
||||
if (dest_i_start >= dest->totlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
dest_i = dest_i_start;
|
||||
|
||||
while (dest_i < dest->totlayer && dest->layers[dest_i].type == source->layers[src_i].type) {
|
||||
/* if we found a matching layer, copy the data */
|
||||
if (dest->layers[dest_i].type == source->layers[src_i].type &&
|
||||
STREQ(dest->layers[dest_i].name, source->layers[src_i].name)) {
|
||||
void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
|
||||
void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
|
||||
const uint size = typeInfo->size;
|
||||
|
||||
// swap data
|
||||
char *bsrc = (char *)src_data;
|
||||
char *bdst = (char *)dest_data;
|
||||
|
||||
for (int j = 0; j < size; j++) {
|
||||
char t = *bsrc;
|
||||
*bsrc = *bdst;
|
||||
*bdst = t;
|
||||
|
||||
bsrc++;
|
||||
bdst++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dest_i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CustomData_bmesh_copy_data_exclude_by_type(const CustomData *source,
|
||||
CustomData *dest,
|
||||
void *src_block,
|
||||
@@ -3775,50 +4081,59 @@ void CustomData_bmesh_copy_data_exclude_by_type(const CustomData *source,
|
||||
}
|
||||
}
|
||||
|
||||
for (int dest_i = 0; dest_i < dest->totlayer; dest_i++) {
|
||||
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
|
||||
dest_i++;
|
||||
}
|
||||
|
||||
/* copies a layer at a time */
|
||||
int dest_i = 0;
|
||||
int dest_i_start = 0;
|
||||
|
||||
for (int src_i = 0; src_i < source->totlayer; src_i++) {
|
||||
|
||||
/* find the first dest layer with type >= the source type
|
||||
* (this should work because layers are ordered by type)
|
||||
*/
|
||||
while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) {
|
||||
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
|
||||
dest_i++;
|
||||
while (dest_i_start < dest->totlayer &&
|
||||
dest->layers[dest_i_start].type < source->layers[src_i].type) {
|
||||
dest_i_start++;
|
||||
}
|
||||
|
||||
/* if there are no more dest layers, we're done */
|
||||
if (dest_i >= dest->totlayer) {
|
||||
if (dest_i_start >= dest->totlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we found a matching layer, copy the data */
|
||||
if (dest->layers[dest_i].type == source->layers[src_i].type &&
|
||||
STREQ(dest->layers[dest_i].name, source->layers[src_i].name)) {
|
||||
if (no_mask || ((CD_TYPE_AS_MASK(dest->layers[dest_i].type) & mask_exclude) == 0)) {
|
||||
const void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
|
||||
void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
|
||||
if (typeInfo->copy) {
|
||||
typeInfo->copy(src_data, dest_data, 1);
|
||||
}
|
||||
else {
|
||||
memcpy(dest_data, src_data, typeInfo->size);
|
||||
int dest_i = dest_i_start;
|
||||
|
||||
/*Previously this code was only checking one source layer against one destination.
|
||||
Now it scans all the layers of that type. - joeedh
|
||||
*/
|
||||
while (dest_i < dest->totlayer && dest->layers[dest_i].type == source->layers[src_i].type) {
|
||||
/* if we found a matching layer, copy the data */
|
||||
if (STREQ(dest->layers[dest_i].name, source->layers[src_i].name)) {
|
||||
if (no_mask || ((CD_TYPE_AS_MASK(dest->layers[dest_i].type) & mask_exclude) == 0)) {
|
||||
if (dest->layers[dest_i].flag & CD_FLAG_ELEM_NOCOPY) {
|
||||
break;
|
||||
}
|
||||
|
||||
const void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
|
||||
void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
|
||||
const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
|
||||
if (typeInfo->copy) {
|
||||
typeInfo->copy(src_data, dest_data, 1);
|
||||
}
|
||||
else {
|
||||
memcpy(dest_data, src_data, typeInfo->size);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* if there are multiple source & dest layers of the same type,
|
||||
* we don't want to copy all source layers to the same dest, so
|
||||
* increment dest_i
|
||||
*/
|
||||
dest_i++;
|
||||
}
|
||||
}
|
||||
|
||||
while (dest_i < dest->totlayer) {
|
||||
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
|
||||
dest_i++;
|
||||
}
|
||||
}
|
||||
|
||||
void CustomData_bmesh_copy_data(const CustomData *source,
|
||||
|
@@ -150,6 +150,7 @@ bool BKE_object_data_transfer_get_dttypes_capacity(const int dtdata_types,
|
||||
case DT_TYPE_UV:
|
||||
ret = true;
|
||||
break;
|
||||
case DT_TYPE_PROPCOL:
|
||||
case DT_TYPE_VCOL:
|
||||
*r_advanced_mixing = true;
|
||||
*r_threshold = true;
|
||||
@@ -230,12 +231,12 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type)
|
||||
return CD_FAKE_SHARP;
|
||||
case DT_TYPE_FREESTYLE_FACE:
|
||||
return CD_FREESTYLE_FACE;
|
||||
|
||||
case DT_TYPE_VCOL:
|
||||
return CD_MLOOPCOL;
|
||||
case DT_TYPE_LNOR:
|
||||
return CD_FAKE_LNOR;
|
||||
|
||||
case DT_TYPE_PROPCOL:
|
||||
return CD_PROP_COLOR;
|
||||
default:
|
||||
BLI_assert(0);
|
||||
}
|
||||
@@ -253,6 +254,8 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
|
||||
return DT_MULTILAYER_INDEX_UV;
|
||||
case DT_TYPE_VCOL:
|
||||
return DT_MULTILAYER_INDEX_VCOL;
|
||||
case DT_TYPE_PROPCOL:
|
||||
return DT_MULTILAYER_INDEX_PROPCOL;
|
||||
default:
|
||||
return DT_MULTILAYER_INDEX_INVALID;
|
||||
}
|
||||
|
6175
source/blender/blenkernel/intern/dyntopo.c
Normal file
6175
source/blender/blenkernel/intern/dyntopo.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -184,7 +184,7 @@ static void idp_repr_fn_recursive(struct ReprState *state, const IDProperty *pro
|
||||
const ID *id = prop->data.pointer;
|
||||
if (id != NULL) {
|
||||
STR_APPEND_STR("bpy.data.");
|
||||
STR_APPEND_STR(BKE_idtype_idcode_to_name_plural(GS(id->name)));
|
||||
STR_APPEND_STR(BKE_idtype_idcode_to_name_plural((short)GS(id->name)));
|
||||
STR_APPEND_STR("[");
|
||||
STR_APPEND_STR_QUOTE(id->name + 2);
|
||||
STR_APPEND_STR("]");
|
||||
|
@@ -674,7 +674,7 @@ ID *BKE_id_copy(Main *bmain, const ID *id)
|
||||
* Invokes the appropriate copy method for the block and returns the result in
|
||||
* newid, unless test. Returns true if the block can be copied.
|
||||
*/
|
||||
ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplicate_flags)
|
||||
ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const uint duplicate_flags)
|
||||
{
|
||||
if (id == NULL) {
|
||||
return id;
|
||||
|
@@ -1123,14 +1123,15 @@ Mesh *BKE_mesh_copy_for_eval(const Mesh *source, bool reference)
|
||||
return result;
|
||||
}
|
||||
|
||||
BMesh *BKE_mesh_to_bmesh_ex(const Mesh *me,
|
||||
BMesh *BKE_mesh_to_bmesh_ex(const Object *ob,
|
||||
const Mesh *me,
|
||||
const struct BMeshCreateParams *create_params,
|
||||
const struct BMeshFromMeshParams *convert_params)
|
||||
{
|
||||
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
|
||||
|
||||
BMesh *bm = BM_mesh_create(&allocsize, create_params);
|
||||
BM_mesh_bm_from_me(bm, me, convert_params);
|
||||
BM_mesh_bm_from_me((Object *)ob, bm, me, convert_params);
|
||||
|
||||
return bm;
|
||||
}
|
||||
@@ -1140,7 +1141,8 @@ BMesh *BKE_mesh_to_bmesh(Mesh *me,
|
||||
const bool add_key_index,
|
||||
const struct BMeshCreateParams *params)
|
||||
{
|
||||
return BKE_mesh_to_bmesh_ex(me,
|
||||
return BKE_mesh_to_bmesh_ex(ob,
|
||||
me,
|
||||
params,
|
||||
&(struct BMeshFromMeshParams){
|
||||
.calc_face_normal = false,
|
||||
@@ -1156,8 +1158,13 @@ Mesh *BKE_mesh_from_bmesh_nomain(BMesh *bm,
|
||||
{
|
||||
BLI_assert(params->calc_object_remap == false);
|
||||
Mesh *mesh = BKE_id_new_nomain(ID_ME, NULL);
|
||||
BM_mesh_bm_to_me(NULL, bm, mesh, params);
|
||||
BKE_mesh_copy_parameters_for_eval(mesh, me_settings);
|
||||
|
||||
BM_mesh_bm_to_me(NULL, NULL, bm, mesh, params);
|
||||
|
||||
if (me_settings) {
|
||||
BKE_mesh_copy_parameters_for_eval(mesh, me_settings);
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
@@ -67,6 +67,12 @@ class FairingContext {
|
||||
/* Get the other vertex index for a loop. */
|
||||
virtual int other_vertex_index_from_loop(const int loop, const uint v) = 0;
|
||||
|
||||
virtual float *vertex_deformation_co_get(const int v) = 0;
|
||||
virtual void vertex_deformation_co_set(const int v, const float co[3]) = 0;
|
||||
|
||||
virtual int vertex_index_from_loop(const int loop) = 0;
|
||||
virtual float cotangent_loop_weight_get(const int loop) = 0;
|
||||
|
||||
int vertex_count_get()
|
||||
{
|
||||
return totvert_;
|
||||
@@ -74,7 +80,7 @@ class FairingContext {
|
||||
|
||||
int loop_count_get()
|
||||
{
|
||||
return totvert_;
|
||||
return totloop_;
|
||||
}
|
||||
|
||||
MeshElemMap *vertex_loop_map_get(const int v)
|
||||
@@ -82,11 +88,6 @@ class FairingContext {
|
||||
return &vlmap_[v];
|
||||
}
|
||||
|
||||
float *vertex_deformation_co_get(const int v)
|
||||
{
|
||||
return co_[v];
|
||||
}
|
||||
|
||||
virtual ~FairingContext() = default;
|
||||
|
||||
void fair_vertices(bool *affected,
|
||||
@@ -99,8 +100,6 @@ class FairingContext {
|
||||
}
|
||||
|
||||
protected:
|
||||
Vector<float *> co_;
|
||||
|
||||
int totvert_;
|
||||
int totloop_;
|
||||
|
||||
@@ -123,8 +122,10 @@ class FairingContext {
|
||||
EIG_linear_solver_matrix_add(solver, i, j, -multiplier);
|
||||
return;
|
||||
}
|
||||
|
||||
const float *co = vertex_deformation_co_get(v);
|
||||
for (int j = 0; j < 3; j++) {
|
||||
EIG_linear_solver_right_hand_side_add(solver, j, i, multiplier * co_[v][j]);
|
||||
EIG_linear_solver_right_hand_side_add(solver, j, i, multiplier * co[j]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -191,9 +192,11 @@ class FairingContext {
|
||||
for (auto item : vert_col_map.items()) {
|
||||
const int v = item.key;
|
||||
const int col = item.value;
|
||||
float co[3];
|
||||
for (int j = 0; j < 3; j++) {
|
||||
co_[v][j] = EIG_linear_solver_variable_get(solver, j, col);
|
||||
co[j] = EIG_linear_solver_variable_get(solver, j, col);
|
||||
}
|
||||
vertex_deformation_co_set(v, co);
|
||||
}
|
||||
|
||||
/* Free solver data */
|
||||
@@ -213,26 +216,33 @@ class MeshFairingContext : public FairingContext {
|
||||
mloop_ = mesh->mloop;
|
||||
BKE_mesh_vert_loop_map_create(&vlmap_,
|
||||
&vlmap_mem_,
|
||||
mesh->mvert,
|
||||
mesh->medge,
|
||||
mesh->mpoly,
|
||||
mesh->mloop,
|
||||
mesh->totvert,
|
||||
mesh->totpoly,
|
||||
mesh->totloop,
|
||||
false);
|
||||
|
||||
BKE_mesh_edge_loop_map_create(&elmap_,
|
||||
&elmap_mem_,
|
||||
mesh->medge,
|
||||
mesh->totedge,
|
||||
mesh->mpoly,
|
||||
mesh->totpoly,
|
||||
mesh->mloop,
|
||||
mesh->totloop);
|
||||
|
||||
/* Deformation coords. */
|
||||
co_.reserve(mesh->totvert);
|
||||
if (deform_mverts) {
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
co_[i] = deform_mverts[i].co;
|
||||
}
|
||||
deform_mvert_ = deform_mverts;
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < mesh->totvert; i++) {
|
||||
co_[i] = mesh->mvert[i].co;
|
||||
}
|
||||
deform_mvert_ = mesh->mvert;
|
||||
}
|
||||
|
||||
loop_to_poly_map_.reserve(mesh->totloop);
|
||||
loop_to_poly_map_.resize(mesh->totloop);
|
||||
for (int i = 0; i < mesh->totpoly; i++) {
|
||||
for (int l = 0; l < mesh->mpoly[i].totloop; l++) {
|
||||
loop_to_poly_map_[l + mesh->mpoly[i].loopstart] = i;
|
||||
@@ -244,6 +254,18 @@ class MeshFairingContext : public FairingContext {
|
||||
{
|
||||
MEM_SAFE_FREE(vlmap_);
|
||||
MEM_SAFE_FREE(vlmap_mem_);
|
||||
MEM_SAFE_FREE(elmap_);
|
||||
MEM_SAFE_FREE(elmap_mem_);
|
||||
}
|
||||
|
||||
float *vertex_deformation_co_get(const int v)
|
||||
{
|
||||
return deform_mvert_[v].co;
|
||||
}
|
||||
|
||||
void vertex_deformation_co_set(const int v, const float co[3])
|
||||
{
|
||||
copy_v3_v3(deform_mvert_[v].co, co);
|
||||
}
|
||||
|
||||
void adjacents_coords_from_loop(const int loop,
|
||||
@@ -253,8 +275,8 @@ class MeshFairingContext : public FairingContext {
|
||||
const int vert = mloop_[loop].v;
|
||||
const MPoly *p = &mpoly_[loop_to_poly_map_[loop]];
|
||||
const int corner = poly_find_loop_from_vert(p, &mloop_[p->loopstart], vert);
|
||||
copy_v3_v3(r_adj_next, co_[ME_POLY_LOOP_NEXT(mloop_, p, corner)->v]);
|
||||
copy_v3_v3(r_adj_prev, co_[ME_POLY_LOOP_PREV(mloop_, p, corner)->v]);
|
||||
copy_v3_v3(r_adj_next, deform_mvert_[ME_POLY_LOOP_NEXT(mloop_, p, corner)->v].co);
|
||||
copy_v3_v3(r_adj_prev, deform_mvert_[ME_POLY_LOOP_PREV(mloop_, p, corner)->v].co);
|
||||
}
|
||||
|
||||
int other_vertex_index_from_loop(const int loop, const uint v) override
|
||||
@@ -266,12 +288,28 @@ class MeshFairingContext : public FairingContext {
|
||||
return e->v1;
|
||||
}
|
||||
|
||||
int vertex_index_from_loop(const int loop) override
|
||||
{
|
||||
return mloop_[loop].v;
|
||||
}
|
||||
|
||||
float cotangent_loop_weight_get(const int UNUSED(loop)) override
|
||||
{
|
||||
/* TODO: Implement cotangent loop weights for meshes. */
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
protected:
|
||||
Mesh *mesh_;
|
||||
MLoop *mloop_;
|
||||
MPoly *mpoly_;
|
||||
MEdge *medge_;
|
||||
Vector<int> loop_to_poly_map_;
|
||||
|
||||
MVert *deform_mvert_;
|
||||
|
||||
MeshElemMap *elmap_;
|
||||
int *elmap_mem_;
|
||||
};
|
||||
|
||||
class BMeshFairingContext : public FairingContext {
|
||||
@@ -285,14 +323,7 @@ class BMeshFairingContext : public FairingContext {
|
||||
BM_mesh_elem_table_ensure(bm, BM_VERT);
|
||||
BM_mesh_elem_index_ensure(bm, BM_LOOP);
|
||||
|
||||
/* Deformation coords. */
|
||||
co_.reserve(bm->totvert);
|
||||
for (int i = 0; i < bm->totvert; i++) {
|
||||
BMVert *v = BM_vert_at_index(bm, i);
|
||||
co_[i] = v->co;
|
||||
}
|
||||
|
||||
bmloop_.reserve(bm->totloop);
|
||||
bmloop_.resize(bm->totloop);
|
||||
vlmap_ = (MeshElemMap *)MEM_calloc_arrayN(sizeof(MeshElemMap), bm->totvert, "bmesh loop map");
|
||||
vlmap_mem_ = (int *)MEM_malloc_arrayN(sizeof(int), bm->totloop, "bmesh loop map mempool");
|
||||
|
||||
@@ -307,6 +338,7 @@ class BMeshFairingContext : public FairingContext {
|
||||
int loop_count = 0;
|
||||
const int vert_index = BM_elem_index_get(v);
|
||||
vlmap_[vert_index].indices = &vlmap_mem_[index_iter];
|
||||
|
||||
BM_ITER_ELEM (l, &loop_iter, v, BM_LOOPS_OF_VERT) {
|
||||
const int loop_index = BM_elem_index_get(l);
|
||||
bmloop_[loop_index] = l;
|
||||
@@ -324,6 +356,16 @@ class BMeshFairingContext : public FairingContext {
|
||||
MEM_SAFE_FREE(vlmap_mem_);
|
||||
}
|
||||
|
||||
float *vertex_deformation_co_get(const int v)
|
||||
{
|
||||
return BM_vert_at_index(bm, v)->co;
|
||||
}
|
||||
|
||||
void vertex_deformation_co_set(const int v, const float co[3])
|
||||
{
|
||||
copy_v3_v3(BM_vert_at_index(bm, v)->co, co);
|
||||
}
|
||||
|
||||
void adjacents_coords_from_loop(const int loop,
|
||||
float r_adj_next[3],
|
||||
float r_adj_prev[3]) override
|
||||
@@ -340,6 +382,47 @@ class BMeshFairingContext : public FairingContext {
|
||||
return BM_elem_index_get(bm_other_vert);
|
||||
}
|
||||
|
||||
int vertex_index_from_loop(const int loop) override
|
||||
{
|
||||
return BM_elem_index_get(bmloop_[loop]->v);
|
||||
}
|
||||
|
||||
float cotangent_loop_weight_get(const int loop) override
|
||||
{
|
||||
return 1.0f;
|
||||
|
||||
/* TODO: enable this when it works. */
|
||||
BMLoop *l = bmloop_[loop];
|
||||
float *co_c[2];
|
||||
int co_c_count = 1;
|
||||
|
||||
float *co_a = l->v->co;
|
||||
float *co_b = l->next->v->co;
|
||||
co_c[0] = l->prev->v->co;
|
||||
if (!BM_edge_is_boundary(l->e)) {
|
||||
co_c_count = 2;
|
||||
co_c[1] = l->radial_next->next->next->v->co;
|
||||
}
|
||||
|
||||
float weight = 0.0f;
|
||||
for (int c = 0; c < co_c_count; c++) {
|
||||
float v1[3];
|
||||
float v2[3];
|
||||
sub_v3_v3v3(v1, co_a, co_c[c]);
|
||||
sub_v3_v3v3(v2, co_b, co_c[c]);
|
||||
const float angle = angle_v3v3(v1, v2);
|
||||
const float tangent = tan(angle);
|
||||
if (tangent != 0) {
|
||||
weight += 1.0f / tangent;
|
||||
}
|
||||
else {
|
||||
weight += 1e-4;
|
||||
}
|
||||
}
|
||||
weight *= 0.5f;
|
||||
return weight;
|
||||
}
|
||||
|
||||
protected:
|
||||
BMesh *bm;
|
||||
Vector<BMLoop *> bmloop_;
|
||||
@@ -350,25 +433,35 @@ class UniformVertexWeight : public VertexWeight {
|
||||
UniformVertexWeight(FairingContext *fairing_context)
|
||||
{
|
||||
const int totvert = fairing_context->vertex_count_get();
|
||||
vertex_weights_.reserve(totvert);
|
||||
fairing_context_ = fairing_context;
|
||||
vertex_weights_.resize(totvert);
|
||||
cached_.resize(totvert);
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
const int tot_loop = fairing_context->vertex_loop_map_get(i)->count;
|
||||
if (tot_loop != 0) {
|
||||
vertex_weights_[i] = 1.0f / tot_loop;
|
||||
}
|
||||
else {
|
||||
vertex_weights_[i] = FLT_MAX;
|
||||
}
|
||||
cached_[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
float weight_at_index(const int index) override
|
||||
{
|
||||
if (!cached_[index]) {
|
||||
vertex_weights_[index] = uniform_weight_at_index(index);
|
||||
cached_[index] = true;
|
||||
}
|
||||
return vertex_weights_[index];
|
||||
}
|
||||
|
||||
private:
|
||||
float uniform_weight_at_index(const int index)
|
||||
{
|
||||
const int tot_loop = fairing_context_->vertex_loop_map_get(index)->count;
|
||||
if (tot_loop != 0) {
|
||||
return 1.0f / tot_loop;
|
||||
}
|
||||
return FLT_MAX;
|
||||
}
|
||||
Vector<float> vertex_weights_;
|
||||
Vector<bool> cached_;
|
||||
FairingContext *fairing_context_;
|
||||
};
|
||||
|
||||
class VoronoiVertexWeight : public VertexWeight {
|
||||
@@ -376,52 +469,65 @@ class VoronoiVertexWeight : public VertexWeight {
|
||||
public:
|
||||
VoronoiVertexWeight(FairingContext *fairing_context)
|
||||
{
|
||||
fairing_context_ = fairing_context;
|
||||
|
||||
const int totvert = fairing_context->vertex_count_get();
|
||||
vertex_weights_.reserve(totvert);
|
||||
vertex_weights_.resize(totvert);
|
||||
cached_.resize(totvert);
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
|
||||
float area = 0.0f;
|
||||
float a[3];
|
||||
copy_v3_v3(a, fairing_context->vertex_deformation_co_get(i));
|
||||
const float acute_threshold = M_PI_2;
|
||||
|
||||
MeshElemMap *vlmap_elem = fairing_context->vertex_loop_map_get(i);
|
||||
for (int l = 0; l < vlmap_elem->count; l++) {
|
||||
const int l_index = vlmap_elem->indices[l];
|
||||
|
||||
float b[3], c[3], d[3];
|
||||
fairing_context->adjacents_coords_from_loop(l_index, b, c);
|
||||
|
||||
if (angle_v3v3v3(c, fairing_context->vertex_deformation_co_get(i), b) < acute_threshold) {
|
||||
calc_circumcenter(d, a, b, c);
|
||||
}
|
||||
else {
|
||||
add_v3_v3v3(d, b, c);
|
||||
mul_v3_fl(d, 0.5f);
|
||||
}
|
||||
|
||||
float t[3];
|
||||
add_v3_v3v3(t, a, b);
|
||||
mul_v3_fl(t, 0.5f);
|
||||
area += area_tri_v3(a, t, d);
|
||||
|
||||
add_v3_v3v3(t, a, c);
|
||||
mul_v3_fl(t, 0.5f);
|
||||
area += area_tri_v3(a, d, t);
|
||||
}
|
||||
|
||||
vertex_weights_[i] = area != 0.0f ? 1.0f / area : 1e12;
|
||||
cached_[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
float weight_at_index(const int index) override
|
||||
{
|
||||
if (!cached_[index]) {
|
||||
vertex_weights_[index] = voronoi_weight_at_index(index);
|
||||
cached_[index] = true;
|
||||
}
|
||||
return vertex_weights_[index];
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<float> vertex_weights_;
|
||||
Vector<bool> cached_;
|
||||
FairingContext *fairing_context_;
|
||||
|
||||
float voronoi_weight_at_index(const int index)
|
||||
{
|
||||
float area = 0.0f;
|
||||
float a[3];
|
||||
copy_v3_v3(a, fairing_context_->vertex_deformation_co_get(index));
|
||||
const float acute_threshold = M_PI_2;
|
||||
|
||||
MeshElemMap *vlmap_elem = fairing_context_->vertex_loop_map_get(index);
|
||||
for (int l = 0; l < vlmap_elem->count; l++) {
|
||||
const int l_index = vlmap_elem->indices[l];
|
||||
|
||||
float b[3], c[3], d[3];
|
||||
fairing_context_->adjacents_coords_from_loop(l_index, b, c);
|
||||
|
||||
if (angle_v3v3v3(c, fairing_context_->vertex_deformation_co_get(index), b) <
|
||||
acute_threshold) {
|
||||
calc_circumcenter(d, a, b, c);
|
||||
}
|
||||
else {
|
||||
add_v3_v3v3(d, b, c);
|
||||
mul_v3_fl(d, 0.5f);
|
||||
}
|
||||
|
||||
float t[3];
|
||||
add_v3_v3v3(t, a, b);
|
||||
mul_v3_fl(t, 0.5f);
|
||||
area += area_tri_v3(a, t, d);
|
||||
|
||||
add_v3_v3v3(t, a, c);
|
||||
mul_v3_fl(t, 0.5f);
|
||||
area += area_tri_v3(a, d, t);
|
||||
}
|
||||
|
||||
return area != 0.0f ? 1.0f / area : 1e12;
|
||||
}
|
||||
|
||||
void calc_circumcenter(float r[3], const float a[3], const float b[3], const float c[3])
|
||||
{
|
||||
@@ -462,6 +568,35 @@ class UniformLoopWeight : public LoopWeight {
|
||||
}
|
||||
};
|
||||
|
||||
class CotangentLoopWeight : public LoopWeight {
|
||||
public:
|
||||
CotangentLoopWeight(FairingContext *fairing_context)
|
||||
{
|
||||
const int totloop = fairing_context->loop_count_get();
|
||||
fairing_context_ = fairing_context;
|
||||
loop_weights_.resize(totloop);
|
||||
cached_.resize(totloop);
|
||||
for (int i = 0; i < totloop; i++) {
|
||||
cached_[i] = false;
|
||||
}
|
||||
}
|
||||
~CotangentLoopWeight() = default;
|
||||
|
||||
float weight_at_index(const int index) override
|
||||
{
|
||||
if (!cached_[index]) {
|
||||
loop_weights_[index] = fairing_context_->cotangent_loop_weight_get(index);
|
||||
cached_[index] = true;
|
||||
}
|
||||
return loop_weights_[index];
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<float> loop_weights_;
|
||||
Vector<bool> cached_;
|
||||
FairingContext *fairing_context_;
|
||||
};
|
||||
|
||||
static void prefair_and_fair_vertices(FairingContext *fairing_context,
|
||||
bool *affected_vertices,
|
||||
const eMeshFairingDepth depth)
|
||||
@@ -469,18 +604,23 @@ static void prefair_and_fair_vertices(FairingContext *fairing_context,
|
||||
/* Prefair. */
|
||||
UniformVertexWeight *uniform_vertex_weights = new UniformVertexWeight(fairing_context);
|
||||
UniformLoopWeight *uniform_loop_weights = new UniformLoopWeight();
|
||||
fairing_context->fair_vertices(
|
||||
affected_vertices, depth, uniform_vertex_weights, uniform_loop_weights);
|
||||
fairing_context->fair_vertices(affected_vertices,
|
||||
MESH_FAIRING_DEPTH_POSITION,
|
||||
uniform_vertex_weights,
|
||||
uniform_loop_weights);
|
||||
|
||||
delete uniform_vertex_weights;
|
||||
delete uniform_loop_weights;
|
||||
|
||||
/* Fair. */
|
||||
VoronoiVertexWeight *voronoi_vertex_weights = new VoronoiVertexWeight(fairing_context);
|
||||
/* TODO: Implement cotangent loop weights. */
|
||||
fairing_context->fair_vertices(
|
||||
affected_vertices, depth, voronoi_vertex_weights, uniform_loop_weights);
|
||||
CotangentLoopWeight *cotangent_loop_weights = new CotangentLoopWeight(fairing_context);
|
||||
|
||||
fairing_context->fair_vertices(
|
||||
affected_vertices, depth, voronoi_vertex_weights, cotangent_loop_weights);
|
||||
|
||||
delete uniform_loop_weights;
|
||||
delete voronoi_vertex_weights;
|
||||
delete cotangent_loop_weights;
|
||||
}
|
||||
|
||||
void BKE_mesh_prefair_and_fair_vertices(struct Mesh *mesh,
|
||||
|
@@ -26,12 +26,16 @@
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_vec_types.h"
|
||||
|
||||
#include "BLI_alloca.h"
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_buffer.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_sort.h"
|
||||
#include "BLI_sort_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BLI_memarena.h"
|
||||
|
||||
@@ -194,6 +198,270 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct DiskCycleSortData {
|
||||
float th;
|
||||
int i, elem;
|
||||
const float *co;
|
||||
} DiskCycleSortData;
|
||||
|
||||
/**
|
||||
* Calculate a normal from a vertex cloud.
|
||||
*
|
||||
* \note We could make a higher quality version that takes all vertices into account.
|
||||
* Currently it finds 4 outer most points returning its normal.
|
||||
*/
|
||||
static void calc_cloud_normal(DiskCycleSortData *varr,
|
||||
int varr_len,
|
||||
float r_normal[3],
|
||||
float r_center[3],
|
||||
int *r_index_tangent)
|
||||
{
|
||||
const float varr_len_inv = 1.0f / (float)varr_len;
|
||||
|
||||
/* Get the center point and collect vector array since we loop over these a lot. */
|
||||
float center[3] = {0.0f, 0.0f, 0.0f};
|
||||
for (int i = 0; i < varr_len; i++) {
|
||||
madd_v3_v3fl(center, varr[i].co, varr_len_inv);
|
||||
}
|
||||
|
||||
/* Find the 'co_a' point from center. */
|
||||
int co_a_index = 0;
|
||||
const float *co_a = NULL;
|
||||
{
|
||||
float dist_sq_max = -1.0f;
|
||||
for (int i = 0; i < varr_len; i++) {
|
||||
const float dist_sq_test = len_squared_v3v3(varr[i].co, center);
|
||||
if (!(dist_sq_test <= dist_sq_max)) {
|
||||
co_a = varr[i].co;
|
||||
co_a_index = i;
|
||||
dist_sq_max = dist_sq_test;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float dir_a[3];
|
||||
sub_v3_v3v3(dir_a, co_a, center);
|
||||
normalize_v3(dir_a);
|
||||
|
||||
const float *co_b = NULL;
|
||||
float dir_b[3] = {0.0f, 0.0f, 0.0f};
|
||||
{
|
||||
float dist_sq_max = -1.0f;
|
||||
for (int i = 0; i < varr_len; i++) {
|
||||
if (varr[i].co == co_a) {
|
||||
continue;
|
||||
}
|
||||
float dir_test[3];
|
||||
sub_v3_v3v3(dir_test, varr[i].co, center);
|
||||
project_plane_normalized_v3_v3v3(dir_test, dir_test, dir_a);
|
||||
const float dist_sq_test = len_squared_v3(dir_test);
|
||||
if (!(dist_sq_test <= dist_sq_max)) {
|
||||
co_b = varr[i].co;
|
||||
dist_sq_max = dist_sq_test;
|
||||
copy_v3_v3(dir_b, dir_test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (varr_len <= 3) {
|
||||
normal_tri_v3(r_normal, center, co_a, co_b);
|
||||
goto finally;
|
||||
}
|
||||
|
||||
normalize_v3(dir_b);
|
||||
|
||||
const float *co_a_opposite = NULL;
|
||||
const float *co_b_opposite = NULL;
|
||||
|
||||
{
|
||||
float dot_a_min = FLT_MAX;
|
||||
float dot_b_min = FLT_MAX;
|
||||
for (int i = 0; i < varr_len; i++) {
|
||||
const float *co_test = varr[i].co;
|
||||
float dot_test;
|
||||
|
||||
if (co_test != co_a) {
|
||||
dot_test = dot_v3v3(dir_a, co_test);
|
||||
if (dot_test < dot_a_min) {
|
||||
dot_a_min = dot_test;
|
||||
co_a_opposite = co_test;
|
||||
}
|
||||
}
|
||||
|
||||
if (co_test != co_b) {
|
||||
dot_test = dot_v3v3(dir_b, co_test);
|
||||
if (dot_test < dot_b_min) {
|
||||
dot_b_min = dot_test;
|
||||
co_b_opposite = co_test;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
normal_quad_v3(r_normal, co_a, co_b, co_a_opposite, co_b_opposite);
|
||||
|
||||
finally:
|
||||
if (r_center != NULL) {
|
||||
copy_v3_v3(r_center, center);
|
||||
}
|
||||
if (r_index_tangent != NULL) {
|
||||
*r_index_tangent = co_a_index;
|
||||
}
|
||||
}
|
||||
|
||||
static bool build_disk_cycle_face(const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
const MEdge *medge,
|
||||
const MVert *mvert,
|
||||
int vertex_i,
|
||||
MeshElemMap *elem,
|
||||
int *doneset,
|
||||
int *donelen,
|
||||
DiskCycleSortData *sortdata)
|
||||
{
|
||||
*donelen = 0;
|
||||
|
||||
for (int i = 0; i < elem->count; i++) {
|
||||
const MPoly *mp = mpoly + elem->indices[i];
|
||||
unsigned int loops[2];
|
||||
|
||||
if (poly_get_adj_loops_from_vert(mp, mloop, (unsigned int)vertex_i, loops)) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if (loops[j] != (unsigned int)vertex_i) {
|
||||
bool ok = true;
|
||||
|
||||
for (int k = 0; k < *donelen; k++) {
|
||||
if ((unsigned int)doneset[k] == loops[j]) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
doneset[*donelen] = (int)loops[j];
|
||||
sortdata[*donelen].elem = elem->indices[i];
|
||||
sortdata[*donelen].co = mvert[loops[j]].co;
|
||||
(*donelen)++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("sort error in sort_disk_cycle_face\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return *donelen == elem->count;
|
||||
}
|
||||
|
||||
static bool build_disk_cycle_loop(const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
const MEdge *medge,
|
||||
const MVert *mvert,
|
||||
int vertex_i,
|
||||
MeshElemMap *elem,
|
||||
int *doneset,
|
||||
int *donelen,
|
||||
DiskCycleSortData *sortdata)
|
||||
{
|
||||
*donelen = 0;
|
||||
|
||||
for (int i = 0; i < elem->count; i++) {
|
||||
int l1 = elem->indices[i];
|
||||
const MLoop *ml = mloop + l1;
|
||||
const MEdge *me = medge + ml->e;
|
||||
|
||||
unsigned int v = me->v1 != (unsigned int)vertex_i ? me->v1 : me->v2;
|
||||
|
||||
sortdata[i].co = mvert[v].co;
|
||||
sortdata[i].elem = l1;
|
||||
sortdata[i].i = i;
|
||||
|
||||
(*donelen)++;
|
||||
}
|
||||
|
||||
return *donelen == elem->count;
|
||||
}
|
||||
|
||||
static bool build_disk_cycle_edge(const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
const MEdge *medge,
|
||||
const MVert *mvert,
|
||||
int vertex_i,
|
||||
MeshElemMap *elem,
|
||||
int *doneset,
|
||||
int *donelen,
|
||||
DiskCycleSortData *sortdata)
|
||||
{
|
||||
*donelen = 0;
|
||||
|
||||
for (int i = 0; i < elem->count; i++) {
|
||||
const MEdge *me = medge + elem->indices[i];
|
||||
|
||||
unsigned int v = me->v1 != (unsigned int)vertex_i ? me->v1 : me->v2;
|
||||
|
||||
sortdata[i].co = mvert[v].co;
|
||||
sortdata[i].elem = elem->indices[i];
|
||||
sortdata[i].i = i;
|
||||
|
||||
(*donelen)++;
|
||||
}
|
||||
|
||||
return *donelen == elem->count;
|
||||
}
|
||||
|
||||
static bool sort_disk_cycle(const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
const MEdge *medge,
|
||||
const MVert *mvert,
|
||||
int vertex_i,
|
||||
MeshElemMap *elem,
|
||||
bool is_loops,
|
||||
bool is_edges)
|
||||
{
|
||||
DiskCycleSortData *sortdata = BLI_array_alloca(sortdata, (unsigned int)elem->count);
|
||||
int *doneset = BLI_array_alloca(doneset, (unsigned int)elem->count);
|
||||
int donelen = 0;
|
||||
|
||||
if (is_loops) {
|
||||
if (!build_disk_cycle_face(
|
||||
mpoly, mloop, medge, mvert, vertex_i, elem, doneset, &donelen, sortdata)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (is_edges) {
|
||||
if (!build_disk_cycle_edge(
|
||||
mpoly, mloop, medge, mvert, vertex_i, elem, doneset, &donelen, sortdata)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!build_disk_cycle_loop(
|
||||
mpoly, mloop, medge, mvert, vertex_i, elem, doneset, &donelen, sortdata)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
float no[3], cent[3];
|
||||
int vadj;
|
||||
|
||||
calc_cloud_normal(sortdata, donelen, no, cent, &vadj);
|
||||
|
||||
for (int i = 0; i < donelen; i++) {
|
||||
sortdata[i].th = angle_signed_on_axis_v3v3v3_v3(sortdata[vadj].co, cent, sortdata[i].co, no);
|
||||
}
|
||||
|
||||
qsort((void *)sortdata, (size_t)donelen, sizeof(DiskCycleSortData), BLI_sortutil_cmp_float);
|
||||
|
||||
for (int i = 0; i < donelen; i++) {
|
||||
elem->indices[i] = sortdata[i].elem;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a map where the key is the vertex and the value is a list
|
||||
* of polys or loops that use that vertex as a corner. The lists are allocated
|
||||
@@ -203,12 +471,15 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
|
||||
*/
|
||||
static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const MVert *mvert,
|
||||
const MEdge *medge,
|
||||
const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
int totvert,
|
||||
int totpoly,
|
||||
int totloop,
|
||||
const bool do_loops)
|
||||
const bool do_loops,
|
||||
const bool sort_disk_cycles)
|
||||
{
|
||||
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, __func__);
|
||||
int *indices, *index_iter;
|
||||
@@ -246,6 +517,12 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
|
||||
}
|
||||
}
|
||||
|
||||
if (sort_disk_cycles) {
|
||||
for (i = 0; i < totvert; i++) {
|
||||
sort_disk_cycle(mpoly, mloop, medge, mvert, i, map + i, do_loops, false);
|
||||
}
|
||||
}
|
||||
|
||||
*r_map = map;
|
||||
*r_mem = indices;
|
||||
}
|
||||
@@ -257,13 +534,26 @@ static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map,
|
||||
*/
|
||||
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const MVert *mvert,
|
||||
const MEdge *medge,
|
||||
const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
int totvert,
|
||||
int totpoly,
|
||||
int totloop)
|
||||
int totloop,
|
||||
const bool sort_disk_cycles)
|
||||
{
|
||||
mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, false);
|
||||
mesh_vert_poly_or_loop_map_create(r_map,
|
||||
r_mem,
|
||||
mvert,
|
||||
medge,
|
||||
mpoly,
|
||||
mloop,
|
||||
totvert,
|
||||
totpoly,
|
||||
totloop,
|
||||
false,
|
||||
sort_disk_cycles);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,13 +563,17 @@ void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map,
|
||||
*/
|
||||
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const MVert *mvert,
|
||||
const MEdge *medge,
|
||||
const MPoly *mpoly,
|
||||
const MLoop *mloop,
|
||||
int totvert,
|
||||
int totpoly,
|
||||
int totloop)
|
||||
int totloop,
|
||||
const bool sort_disk_cycles)
|
||||
{
|
||||
mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true);
|
||||
mesh_vert_poly_or_loop_map_create(
|
||||
r_map, r_mem, mvert, medge, mpoly, mloop, totvert, totpoly, totloop, true, sort_disk_cycles);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,8 +630,13 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map,
|
||||
* is a list of edges that use that vertex as an endpoint.
|
||||
* The lists are allocated from one memory pool.
|
||||
*/
|
||||
void BKE_mesh_vert_edge_map_create(
|
||||
MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge)
|
||||
void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map,
|
||||
int **r_mem,
|
||||
const MVert *mvert,
|
||||
const MEdge *medge,
|
||||
int totvert,
|
||||
int totedge,
|
||||
bool sort_disk_cycles)
|
||||
{
|
||||
MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert-edge map");
|
||||
int *indices = MEM_mallocN(sizeof(int[2]) * (size_t)totedge, "vert-edge map mem");
|
||||
@@ -371,6 +670,12 @@ void BKE_mesh_vert_edge_map_create(
|
||||
map[v[1]].count++;
|
||||
}
|
||||
|
||||
if (sort_disk_cycles) {
|
||||
for (i = 0; i < totvert; i++) {
|
||||
sort_disk_cycle(NULL, NULL, medge, mvert, i, map + i, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
*r_map = map;
|
||||
*r_mem = indices;
|
||||
}
|
||||
|
@@ -379,8 +379,16 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
|
||||
|
||||
/* Can we optimize by reusing an old `pmap`? How do we know an old `pmap` is stale? */
|
||||
/* When called by `MOD_array.c` the `cddm` has just been created, so it has no valid `pmap`. */
|
||||
BKE_mesh_vert_poly_map_create(
|
||||
&poly_map, &poly_map_mem, mesh->mpoly, mesh->mloop, totvert, totpoly, totloop);
|
||||
BKE_mesh_vert_poly_map_create(&poly_map,
|
||||
&poly_map_mem,
|
||||
mesh->mvert,
|
||||
mesh->medge,
|
||||
mesh->mpoly,
|
||||
mesh->mloop,
|
||||
totvert,
|
||||
totpoly,
|
||||
totloop,
|
||||
false);
|
||||
} /* done preparing for fast poly compare */
|
||||
|
||||
mp = mesh->mpoly;
|
||||
|
@@ -41,7 +41,8 @@
|
||||
|
||||
#include "MOD_modifiertypes.h"
|
||||
|
||||
Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(MirrorModifierData *mmd,
|
||||
Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(Object *ob,
|
||||
MirrorModifierData *mmd,
|
||||
const Mesh *mesh,
|
||||
int axis,
|
||||
const float plane_co[3],
|
||||
@@ -58,7 +59,8 @@ Mesh *BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(MirrorModifierData *mm
|
||||
BMIter viter;
|
||||
BMVert *v, *v_next;
|
||||
|
||||
bm = BKE_mesh_to_bmesh_ex(mesh,
|
||||
bm = BKE_mesh_to_bmesh_ex(ob,
|
||||
mesh,
|
||||
&(struct BMeshCreateParams){0},
|
||||
&(struct BMeshFromMeshParams){
|
||||
.calc_face_normal = true,
|
||||
@@ -102,7 +104,8 @@ void BKE_mesh_mirror_apply_mirror_on_axis(struct Main *bmain,
|
||||
const int axis,
|
||||
const float dist)
|
||||
{
|
||||
BMesh *bm = BKE_mesh_to_bmesh_ex(mesh,
|
||||
BMesh *bm = BKE_mesh_to_bmesh_ex(NULL,
|
||||
mesh,
|
||||
&(struct BMeshCreateParams){
|
||||
.use_toolflags = 1,
|
||||
},
|
||||
@@ -121,6 +124,7 @@ void BKE_mesh_mirror_apply_mirror_on_axis(struct Main *bmain,
|
||||
true);
|
||||
|
||||
BM_mesh_bm_to_me(bmain,
|
||||
NULL,
|
||||
bm,
|
||||
mesh,
|
||||
(&(struct BMeshToMeshParams){
|
||||
@@ -207,7 +211,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
||||
Mesh *mesh_bisect = NULL;
|
||||
if (do_bisect) {
|
||||
mesh_bisect = BKE_mesh_mirror_bisect_on_mirror_plane_for_modifier(
|
||||
mmd, mesh, axis, plane_co, plane_no);
|
||||
ob, mmd, mesh, axis, plane_co, plane_no);
|
||||
mesh = mesh_bisect;
|
||||
}
|
||||
|
||||
|
@@ -773,9 +773,11 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
|
||||
|
||||
BKE_mesh_vert_edge_map_create(&vert_to_edge_src_map,
|
||||
&vert_to_edge_src_map_mem,
|
||||
NULL,
|
||||
edges_src,
|
||||
num_verts_src,
|
||||
num_edges_src);
|
||||
num_edges_src,
|
||||
false);
|
||||
|
||||
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_VERTS, 2);
|
||||
nearest.index = -1;
|
||||
@@ -1431,19 +1433,25 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
|
||||
if (use_from_vert) {
|
||||
BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src,
|
||||
&vert_to_loop_map_src_buff,
|
||||
verts_src,
|
||||
edges_src,
|
||||
polys_src,
|
||||
loops_src,
|
||||
num_verts_src,
|
||||
num_polys_src,
|
||||
num_loops_src);
|
||||
num_loops_src,
|
||||
false);
|
||||
if (mode & MREMAP_USE_POLY) {
|
||||
BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src,
|
||||
&vert_to_poly_map_src_buff,
|
||||
verts_src,
|
||||
edges_src,
|
||||
polys_src,
|
||||
loops_src,
|
||||
num_verts_src,
|
||||
num_polys_src,
|
||||
num_loops_src);
|
||||
num_loops_src,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_span.hh"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
@@ -43,8 +44,10 @@
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_mesh_remesh_voxel.h" /* own include */
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_paint.h"
|
||||
|
||||
#include "bmesh_tools.h"
|
||||
|
||||
@@ -65,17 +68,28 @@ using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
|
||||
#ifdef WITH_QUADRIFLOW
|
||||
static Mesh *remesh_quadriflow(const Mesh *input_mesh,
|
||||
int target_faces,
|
||||
int seed,
|
||||
bool preserve_sharp,
|
||||
bool preserve_boundary,
|
||||
bool adaptive_scale,
|
||||
void (*update_cb)(void *, float progress, int *cancel),
|
||||
void *update_cb_data)
|
||||
ATTR_NO_OPT static Mesh *remesh_quadriflow(const Mesh *input_mesh,
|
||||
int target_faces,
|
||||
int seed,
|
||||
bool preserve_sharp,
|
||||
bool preserve_boundary,
|
||||
bool adaptive_scale,
|
||||
void (*update_cb)(void *, float progress, int *cancel),
|
||||
void *update_cb_data)
|
||||
{
|
||||
/* Ensure that the triangulated mesh data is up to data */
|
||||
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(input_mesh);
|
||||
MeshElemMap *epmap = nullptr;
|
||||
int *epmem = nullptr;
|
||||
|
||||
BKE_mesh_edge_poly_map_create(&epmap,
|
||||
&epmem,
|
||||
input_mesh->medge,
|
||||
input_mesh->totedge,
|
||||
input_mesh->mpoly,
|
||||
input_mesh->totpoly,
|
||||
input_mesh->mloop,
|
||||
input_mesh->totloop);
|
||||
|
||||
/* Gather the required data for export to the internal quadriflow mesh format. */
|
||||
MVertTri *verttri = (MVertTri *)MEM_callocN(
|
||||
@@ -86,17 +100,63 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
|
||||
const int totfaces = BKE_mesh_runtime_looptri_len(input_mesh);
|
||||
const int totverts = input_mesh->totvert;
|
||||
Array<float3> verts(totverts);
|
||||
Array<int> faces(totfaces * 3);
|
||||
Array<QuadriflowFace> faces(totfaces);
|
||||
|
||||
for (const int i : IndexRange(totverts)) {
|
||||
verts[i] = input_mesh->mvert[i].co;
|
||||
}
|
||||
|
||||
int *fsets = (int *)CustomData_get_layer(&input_mesh->pdata, CD_SCULPT_FACE_SETS);
|
||||
|
||||
for (const int i : IndexRange(totfaces)) {
|
||||
MVertTri &vt = verttri[i];
|
||||
faces[i * 3] = vt.tri[0];
|
||||
faces[i * 3 + 1] = vt.tri[1];
|
||||
faces[i * 3 + 2] = vt.tri[2];
|
||||
faces[i].eflag[0] = faces[i].eflag[1] = faces[i].eflag[2] = 0;
|
||||
|
||||
faces[i].v[0] = vt.tri[0];
|
||||
faces[i].v[1] = vt.tri[1];
|
||||
faces[i].v[2] = vt.tri[2];
|
||||
|
||||
for (const int j : IndexRange(3)) {
|
||||
MLoop *l = input_mesh->mloop + looptri[i].tri[j];
|
||||
MEdge *e = input_mesh->medge + l->e;
|
||||
|
||||
if (e->flag & ME_SHARP) {
|
||||
faces[i].eflag[j] |= QFLOW_CONSTRAINED;
|
||||
continue;
|
||||
}
|
||||
|
||||
MeshElemMap *melem = epmap + looptri[i].poly;
|
||||
|
||||
if (melem->count == 1) {
|
||||
faces[i].eflag[j] |= QFLOW_CONSTRAINED;
|
||||
continue;
|
||||
}
|
||||
|
||||
int fset = 0;
|
||||
int mat_nr = 0;
|
||||
|
||||
for (int k : IndexRange(melem->count)) {
|
||||
MPoly *p = input_mesh->mpoly + melem->indices[k];
|
||||
|
||||
if (k > 0 && p->mat_nr != mat_nr) {
|
||||
faces[i].eflag[j] |= QFLOW_CONSTRAINED;
|
||||
continue;
|
||||
}
|
||||
|
||||
mat_nr = (int)p->mat_nr;
|
||||
|
||||
if (fsets) {
|
||||
int fset2 = fsets[melem->indices[k]];
|
||||
|
||||
if (k > 0 && abs(fset) != abs(fset2)) {
|
||||
faces[i].eflag[j] |= QFLOW_CONSTRAINED;
|
||||
break;
|
||||
}
|
||||
|
||||
fset = fset2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill out the required input data */
|
||||
@@ -158,6 +218,14 @@ static Mesh *remesh_quadriflow(const Mesh *input_mesh,
|
||||
MEM_freeN(qrd.out_faces);
|
||||
MEM_freeN(qrd.out_verts);
|
||||
|
||||
if (epmap) {
|
||||
MEM_freeN((void *)epmap);
|
||||
}
|
||||
|
||||
if (epmem) {
|
||||
MEM_freeN((void *)epmem);
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
#endif
|
||||
@@ -328,6 +396,78 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source)
|
||||
free_bvhtree_from_mesh(&bvhtree);
|
||||
}
|
||||
|
||||
void BKE_mesh_remesh_sculpt_array_update(Object *ob, Mesh *target, Mesh *source)
|
||||
{
|
||||
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
if (!ss) {
|
||||
return;
|
||||
}
|
||||
|
||||
SculptArray *array = ss->array;
|
||||
if (!array) {
|
||||
return;
|
||||
}
|
||||
|
||||
BVHTreeFromMesh bvhtree = {nullptr};
|
||||
bvhtree.nearest_callback = nullptr;
|
||||
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
|
||||
MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
|
||||
|
||||
const int target_totvert = target->totvert;
|
||||
|
||||
int *target_copy_index = (int *)MEM_malloc_arrayN(sizeof(int), target_totvert, "target_copy_index");
|
||||
int *target_symmertry = (int *)MEM_malloc_arrayN(sizeof(int), target_totvert, "target_copy_index");
|
||||
float (*target_orco)[3] = (float (*)[3])MEM_malloc_arrayN(target->totvert, sizeof(float) * 3, "array orco");
|
||||
|
||||
for (int i = 0; i < target_totvert; i++) {
|
||||
target_copy_index[i] = -1;
|
||||
target_symmertry[i] = 0;
|
||||
copy_v3_v3(target_orco[i], target->mvert[i].co);
|
||||
}
|
||||
|
||||
for (int i = 0; i < target->totvert; i++) {
|
||||
float from_co[3];
|
||||
BVHTreeNearest nearest;
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = FLT_MAX;
|
||||
copy_v3_v3(from_co, target_verts[i].co);
|
||||
BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
|
||||
if (nearest.index != -1) {
|
||||
target_copy_index[i] = array->copy_index[nearest.index];
|
||||
target_symmertry[i] = array->symmetry_pass[nearest.index];
|
||||
}
|
||||
}
|
||||
free_bvhtree_from_mesh(&bvhtree);
|
||||
|
||||
MEM_freeN(array->copy_index);
|
||||
MEM_freeN(array->symmetry_pass);
|
||||
MEM_freeN(array->orco);
|
||||
|
||||
array->copy_index = target_copy_index;
|
||||
array->symmetry_pass = target_symmertry;
|
||||
array->orco = target_orco;
|
||||
|
||||
for (int i = 0; i < target->totvert; i++) {
|
||||
int array_index = target_copy_index[i];
|
||||
int array_symm_pass = target_symmertry[i];
|
||||
if (array_index == -1) {
|
||||
continue;
|
||||
}
|
||||
SculptArrayCopy *copy = &array->copies[array_symm_pass][array_index];
|
||||
float co[3];
|
||||
float source_origin_symm[3];
|
||||
copy_v3_v3(co, target->mvert[i].co);
|
||||
/* TODO: MAke symmetry work here. */
|
||||
//flip_v3_v3(source_origin_symm, array->source_origin, array_symm_pass);
|
||||
mul_v3_m4v3(co, array->source_imat, co);
|
||||
mul_v3_m4v3(co, copy->imat, co);
|
||||
sub_v3_v3v3(co, co, source_origin_symm);
|
||||
copy_v3_v3(array->orco[i], co);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)
|
||||
{
|
||||
BVHTreeFromMesh bvhtree = {nullptr};
|
||||
@@ -375,6 +515,33 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)
|
||||
free_bvhtree_from_mesh(&bvhtree);
|
||||
}
|
||||
|
||||
void BKE_remesh_reproject_materials(Mesh *target, Mesh *source)
|
||||
{
|
||||
BVHTreeFromMesh bvhtree = {nullptr};
|
||||
bvhtree.nearest_callback = nullptr;
|
||||
|
||||
const MPoly *target_polys = (MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY);
|
||||
const MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
|
||||
const MLoop *target_loops = (MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP);
|
||||
|
||||
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(source);
|
||||
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_LOOPTRI, 2);
|
||||
|
||||
for (int i = 0; i < target->totpoly; i++) {
|
||||
float from_co[3];
|
||||
BVHTreeNearest nearest;
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = FLT_MAX;
|
||||
const MPoly *mpoly = &target_polys[i];
|
||||
BKE_mesh_calc_poly_center(mpoly, &target_loops[mpoly->loopstart], target_verts, from_co);
|
||||
BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
|
||||
if (nearest.index != -1) {
|
||||
target->mpoly[i].mat_nr = source->mpoly[looptri[nearest.index].poly].mat_nr;
|
||||
}
|
||||
}
|
||||
free_bvhtree_from_mesh(&bvhtree);
|
||||
}
|
||||
|
||||
void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
|
||||
{
|
||||
BVHTreeFromMesh bvhtree = {nullptr};
|
||||
@@ -415,7 +582,7 @@ struct Mesh *BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh)
|
||||
|
||||
BMeshFromMeshParams bmesh_from_mesh_params{};
|
||||
bmesh_from_mesh_params.calc_face_normal = true;
|
||||
BM_mesh_bm_from_me(bm, mesh, &bmesh_from_mesh_params);
|
||||
BM_mesh_bm_from_me(NULL, bm, mesh, &bmesh_from_mesh_params);
|
||||
|
||||
BMVert *v;
|
||||
BMEdge *ed, *ed_next;
|
||||
@@ -449,7 +616,7 @@ struct Mesh *BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh)
|
||||
if (BM_elem_flag_test(ed, BM_ELEM_TAG)) {
|
||||
float co[3];
|
||||
mid_v3_v3v3(co, ed->v1->co, ed->v2->co);
|
||||
BMVert *vc = BM_edge_collapse(bm, ed, ed->v1, true, true);
|
||||
BMVert *vc = BM_edge_collapse(bm, ed, ed->v1, true, true, false);
|
||||
copy_v3_v3(vc->co, co);
|
||||
}
|
||||
}
|
||||
|
@@ -33,22 +33,31 @@
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_edgehash.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_ccg.h"
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_multires.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_pbvh.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_subdiv.h"
|
||||
#include "BKE_subdiv_ccg.h"
|
||||
#include "BKE_subdiv_eval.h"
|
||||
#include "BKE_subsurf.h"
|
||||
|
||||
#include "BKE_object.h"
|
||||
@@ -57,6 +66,8 @@
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "multires_inline.h"
|
||||
#include "multires_reshape.h"
|
||||
|
||||
#include <math.h>
|
||||
@@ -846,17 +857,461 @@ static void grid_tangent_matrix(float mat[3][3], const CCGKey *key, int x, int y
|
||||
|
||||
typedef struct MultiresThreadedData {
|
||||
DispOp op;
|
||||
MultiResSpace bmop;
|
||||
BMesh *bm;
|
||||
int lvl;
|
||||
CCGElem **gridData, **subGridData;
|
||||
CCGKey *key;
|
||||
CCGKey *sub_key;
|
||||
Subdiv *sd;
|
||||
MPoly *mpoly;
|
||||
MDisps *mdisps;
|
||||
GridPaintMask *grid_paint_mask;
|
||||
int *gridOffset;
|
||||
int cd_mdisps_off, cd_mask_off;
|
||||
int gridSize, dGridSize, dSkip;
|
||||
float (*smat)[3];
|
||||
bool has_grid_mask;
|
||||
} MultiresThreadedData;
|
||||
|
||||
Object *multires_dump_grids_bmesh(Object *bmob, BMesh *bm)
|
||||
{
|
||||
if (!CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
|
||||
printf("multires_dump_grids_bmesh: error: no multires grids\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool spaceset = false;
|
||||
|
||||
if (bm->multiresSpace != MULTIRES_SPACE_ABSOLUTE) {
|
||||
BKE_multires_bmesh_space_set(bmob, bm, MULTIRES_SPACE_ABSOLUTE);
|
||||
spaceset = true;
|
||||
}
|
||||
|
||||
Main *bmain = G.main;
|
||||
char *name = "multires_dump";
|
||||
|
||||
bContext *ctx = CTX_create();
|
||||
CTX_data_main_set(ctx, bmain);
|
||||
CTX_wm_manager_set(ctx, G.main->wm.first);
|
||||
CTX_data_scene_set(ctx, G.main->scenes.first);
|
||||
|
||||
ViewLayer *view_layer = CTX_data_view_layer(ctx);
|
||||
Object *ob = BKE_object_add_only_object(bmain, OB_MESH, name);
|
||||
LayerCollection *layer_collection;
|
||||
|
||||
ob->data = BKE_object_obdata_add_from_type(bmain, OB_MESH, name);
|
||||
DEG_id_tag_update_ex(
|
||||
bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
|
||||
// DEG_id_tag_update_ex(
|
||||
// bmain, &ob->data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
|
||||
|
||||
layer_collection = BKE_layer_collection_get_active(view_layer);
|
||||
BKE_collection_object_add(bmain, layer_collection->collection, ob);
|
||||
|
||||
DEG_id_type_tag(bmain, ID_OB);
|
||||
DEG_relations_tag_update(bmain);
|
||||
if (ob->data != NULL) {
|
||||
DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
|
||||
}
|
||||
|
||||
ob->modifiers.first = ob->modifiers.last = NULL;
|
||||
zero_v3(ob->loc);
|
||||
|
||||
printf("users: %d\n", ob->id.us);
|
||||
|
||||
Mesh *me = ob->data;
|
||||
|
||||
BMIter iter;
|
||||
BMFace *f;
|
||||
|
||||
int cd_mdisp_off = CustomData_get_offset(&bm->ldata, CD_MDISPS);
|
||||
int dimen = 0;
|
||||
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
BMLoop *l = f->l_first;
|
||||
MDisps *md = BM_ELEM_CD_GET_VOID_P(l, cd_mdisp_off);
|
||||
dimen = (int)floor(sqrt(md->totdisp) + 0.00001);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dimen) {
|
||||
printf("multires_dump_grids_bmesh: error: corrupted multires data\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int totvert = bm->totloop * dimen * dimen;
|
||||
int totface = bm->totloop * (dimen - 1) * (dimen - 1);
|
||||
int totloop = totface * 4;
|
||||
|
||||
CustomData_free(&me->vdata, me->totvert);
|
||||
CustomData_free(&me->edata, me->totedge);
|
||||
CustomData_free(&me->fdata, me->totface);
|
||||
CustomData_free(&me->ldata, me->totloop);
|
||||
CustomData_free(&me->pdata, me->totpoly);
|
||||
|
||||
me->totvert = totvert;
|
||||
me->totpoly = totface;
|
||||
me->totloop = totloop;
|
||||
me->totedge = totvert + totface;
|
||||
me->totface = 0;
|
||||
me->act_face = -1;
|
||||
|
||||
EdgeHash *eh = BLI_edgehash_new_ex("multires_dump_bmesh", me->totedge);
|
||||
|
||||
MVert *mvert = me->totvert ?
|
||||
MEM_callocN(sizeof(MVert) * me->totvert, "multires_dump_grids_bmesh.vert") :
|
||||
NULL;
|
||||
MEdge *medge = me->totedge ?
|
||||
MEM_callocN(sizeof(MEdge) * me->totedge, "multires_dump_grids_bmesh.edge") :
|
||||
NULL;
|
||||
MLoop *mloop = me->totloop ?
|
||||
MEM_callocN(sizeof(MLoop) * me->totloop, "multires_dump_grids_bmesh.loop") :
|
||||
NULL;
|
||||
MPoly *mpoly = me->totpoly ?
|
||||
MEM_callocN(sizeof(MPoly) * me->totpoly, "multires_dump_grids_bmesh.poly") :
|
||||
NULL;
|
||||
|
||||
me->cd_flag = 0;
|
||||
|
||||
CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
|
||||
CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
|
||||
CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
|
||||
CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
|
||||
|
||||
BKE_mesh_update_customdata_pointers(me, 0);
|
||||
|
||||
int loopi = 0;
|
||||
int outli = 0;
|
||||
int medi = 0;
|
||||
|
||||
#define VINDEX(i, j) (loopi * dimen * dimen + ((j)*dimen + (i)))
|
||||
|
||||
// CustomData_daata_
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
BMLoop *l = f->l_first;
|
||||
do {
|
||||
MDisps *md = BM_ELEM_CD_GET_VOID_P(l, cd_mdisp_off);
|
||||
|
||||
for (int i = 0; i < dimen; i++) {
|
||||
for (int j = 0; j < dimen; j++) {
|
||||
int vidx = loopi * dimen * dimen + (j * dimen + i);
|
||||
int idx = j * dimen + i;
|
||||
float *co = md->disps[idx];
|
||||
|
||||
MVert *mv = mvert + vidx;
|
||||
copy_v3_v3(mv->co, co);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < dimen - 1; i++) {
|
||||
for (int j = 0; j < dimen - 1; j++) {
|
||||
// do face
|
||||
int fidx = loopi * (dimen - 1) * (dimen - 1) + (j * (dimen - 1) + i);
|
||||
MPoly *mp = mpoly + fidx;
|
||||
|
||||
mp->totloop = 4;
|
||||
mp->loopstart = outli;
|
||||
|
||||
MLoop *ml = mloop + outli;
|
||||
|
||||
ml[0].v = VINDEX(i, j);
|
||||
ml[1].v = VINDEX(i, j + 1);
|
||||
ml[2].v = VINDEX(i + 1, j + 1);
|
||||
ml[3].v = VINDEX(i + 1, j);
|
||||
|
||||
for (int i2 = 0; i2 < 4; i2++) {
|
||||
int a = ml[i2].v, b = ml[(i2 + 1) % 4].v;
|
||||
int e;
|
||||
|
||||
if (!BLI_edgehash_haskey(eh, a, b)) {
|
||||
BLI_edgehash_insert(eh, a, b, (void *)medi);
|
||||
e = medi;
|
||||
|
||||
MEdge *med = medge + medi;
|
||||
|
||||
med->v1 = a;
|
||||
med->v2 = b;
|
||||
|
||||
medi++;
|
||||
}
|
||||
else {
|
||||
e = (int)BLI_edgehash_lookup(eh, a, b);
|
||||
}
|
||||
|
||||
ml[i2].e = e;
|
||||
}
|
||||
|
||||
outli += 4;
|
||||
}
|
||||
}
|
||||
|
||||
loopi++;
|
||||
l = l->next;
|
||||
} while (l != f->l_first);
|
||||
}
|
||||
|
||||
for (int i = 0; i < me->totpoly; i++) {
|
||||
if (!mpoly[i].totloop) {
|
||||
printf("error 1! %d %d\n", i, me->totpoly);
|
||||
}
|
||||
if (mpoly[i].loopstart >= me->totloop) {
|
||||
printf(
|
||||
"error 2! %d %d l: %d totl: %d\n", i, me->totpoly, mpoly[i].loopstart, mpoly[i].totloop);
|
||||
}
|
||||
}
|
||||
|
||||
if (spaceset) {
|
||||
BKE_multires_bmesh_space_set(bmob, bm, MULTIRES_SPACE_TANGENT);
|
||||
}
|
||||
|
||||
BKE_mesh_calc_normals(me);
|
||||
BKE_mesh_tessface_calc(me);
|
||||
|
||||
return ob;
|
||||
}
|
||||
|
||||
//#define LIMIT_MAX_DISPLACEMENT
|
||||
|
||||
static void multires_bmesh_space_set_cb(void *__restrict userdata,
|
||||
const int pidx,
|
||||
const TaskParallelTLS *__restrict UNUSED(tls))
|
||||
{
|
||||
MultiresThreadedData *tdata = userdata;
|
||||
|
||||
int cd_mdisps_off = tdata->cd_mdisps_off;
|
||||
BMesh *bm = tdata->bm;
|
||||
MultiResSpace op = tdata->bmop;
|
||||
BMFace *f = bm->ftable[pidx];
|
||||
int gridSize = tdata->gridSize;
|
||||
|
||||
int S, x, y;
|
||||
|
||||
BMLoop *l;
|
||||
|
||||
#ifdef LIMIT_MAX_DISPLACEMENT
|
||||
l = f->l_first;
|
||||
float cent[3];
|
||||
int tot = 0;
|
||||
|
||||
// get face center to calculate maximum allowable displacement length
|
||||
zero_v3(cent);
|
||||
do {
|
||||
add_v3_v3(cent, l->v->co);
|
||||
tot++;
|
||||
l = l->next;
|
||||
} while (l != f->l_first);
|
||||
|
||||
mul_v3_fl(cent, 1.0f / (float)tot);
|
||||
#endif
|
||||
|
||||
l = f->l_first;
|
||||
S = 0;
|
||||
do {
|
||||
MDisps *mdisp = BM_ELEM_CD_GET_VOID_P(l, cd_mdisps_off);
|
||||
float(*dispgrid)[3] = NULL;
|
||||
|
||||
dispgrid = mdisp->disps;
|
||||
|
||||
#ifdef LIMIT_MAX_DISPLACEMENT
|
||||
/*try to limit numerical instability by clamping max displacement*/
|
||||
|
||||
float maxlen = len_v3v3(l->v->co, cent) * 15.0f;
|
||||
maxlen = MAX2(maxlen, 0.00001f);
|
||||
#endif
|
||||
|
||||
for (y = 0; y < gridSize; y++) {
|
||||
for (x = 0; x < gridSize; x++) {
|
||||
float sco[8], udv[3], vdv[3];
|
||||
float *data = dispgrid[gridSize * y + x];
|
||||
float mat[3][3], disp[3];
|
||||
|
||||
float grid_u = (float)x / (float)(gridSize - 1);
|
||||
float grid_v = (float)y / (float)(gridSize - 1);
|
||||
float u, v;
|
||||
|
||||
int corner = S;
|
||||
if (f->len == 4) {
|
||||
BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &u, &v);
|
||||
}
|
||||
else {
|
||||
u = 1.0 - grid_v;
|
||||
v = 1.0 - grid_u;
|
||||
}
|
||||
|
||||
BKE_subdiv_eval_limit_point_and_derivatives(tdata->sd, l->head.index, u, v, sco, udv, vdv);
|
||||
BKE_multires_construct_tangent_matrix(mat, udv, vdv, f->len == 4 ? corner : 0);
|
||||
|
||||
copy_v3_v3(disp, data);
|
||||
|
||||
switch (op) {
|
||||
case MULTIRES_SPACE_ABSOLUTE:
|
||||
/* Convert displacement to object space
|
||||
* and add to grid points */
|
||||
mul_v3_m3v3(disp, mat, data);
|
||||
add_v3_v3v3(data, disp, sco);
|
||||
break;
|
||||
case MULTIRES_SPACE_TANGENT:
|
||||
/* Calculate displacement between new and old
|
||||
* grid points and convert to tangent space */
|
||||
invert_m3(mat);
|
||||
|
||||
sub_v3_v3v3(disp, data, sco);
|
||||
mul_v3_m3v3(data, mat, disp);
|
||||
|
||||
// try to prevent errors
|
||||
float len = len_v3(data);
|
||||
#ifdef LIMIT_MAX_DISPLACEMENT
|
||||
if (len > maxlen) {
|
||||
mul_v3_fl(data, maxlen / len);
|
||||
}
|
||||
else if (isnan(len)) {
|
||||
zero_v3(data);
|
||||
}
|
||||
#else
|
||||
if (isnan(len)) {
|
||||
zero_v3(data);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S++;
|
||||
l = l->next;
|
||||
} while (l != f->l_first);
|
||||
}
|
||||
|
||||
/* The original version of this function was broken (and subsequently removed)
|
||||
because it didn't properly set the subdivision level; it also used the old
|
||||
multires system. The new subdiv API is now used instead.
|
||||
*/
|
||||
void BKE_multires_bmesh_space_set(Object *ob, BMesh *bm, int mode)
|
||||
{
|
||||
if (!bm->totface || !CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get multires settings
|
||||
MultiresModifierData *mmd = bm->haveMultiResSettings ? &bm->multires : NULL;
|
||||
|
||||
if (!mmd && ob) {
|
||||
mmd = get_multires_modifier(NULL, ob, true);
|
||||
}
|
||||
|
||||
if (!mmd || !CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// cache multires settings in bmesh
|
||||
bm->multiresSpace = mode;
|
||||
|
||||
// create temporary mesh structure
|
||||
Mesh _me, *me = &_me;
|
||||
memset(me, 0, sizeof(Mesh));
|
||||
CustomData_reset(&me->vdata);
|
||||
CustomData_reset(&me->edata);
|
||||
CustomData_reset(&me->ldata);
|
||||
CustomData_reset(&me->fdata);
|
||||
CustomData_reset(&me->pdata);
|
||||
|
||||
CustomData_MeshMasks extra = CD_MASK_DERIVEDMESH;
|
||||
extra.lmask |= CD_MASK_MDISPS;
|
||||
|
||||
BM_mesh_bm_to_me_for_eval(bm, me, &extra);
|
||||
SubdivSettings settings2;
|
||||
|
||||
// copy the settings and then set subdivision level to max
|
||||
MultiresModifierData mmdcpy = *mmd;
|
||||
mmdcpy.lvl = mmdcpy.sculptlvl = mmdcpy.renderlvl = mmdcpy.totlvl;
|
||||
|
||||
// set up subdivision surface
|
||||
BKE_multires_subdiv_settings_init(&settings2, &mmdcpy);
|
||||
Subdiv *sd = BKE_subdiv_new_from_mesh(&settings2, me);
|
||||
BKE_subdiv_eval_begin_from_mesh(sd, me, NULL);
|
||||
|
||||
// create a fake object with .sculpt set to NULL
|
||||
Object fakeob;
|
||||
if (ob) {
|
||||
fakeob = *ob;
|
||||
fakeob.sculpt = NULL;
|
||||
}
|
||||
else {
|
||||
memset(&fakeob, 0, sizeof(fakeob));
|
||||
fakeob.data = me;
|
||||
BLI_addtail(&fakeob.modifiers, &mmdcpy);
|
||||
}
|
||||
|
||||
int i, gridSize;
|
||||
int totpoly = bm->totface;
|
||||
|
||||
// force paranoia recalc of indices and lookup tables
|
||||
bm->elem_index_dirty |= BM_FACE;
|
||||
bm->elem_table_dirty |= BM_FACE;
|
||||
|
||||
BM_mesh_elem_index_ensure(bm, BM_FACE);
|
||||
BM_mesh_elem_table_ensure(bm, BM_FACE);
|
||||
|
||||
gridSize = multires_side_tot[mmd->totlvl];
|
||||
|
||||
int cd_disp_off = CustomData_get_offset(&bm->ldata, CD_MDISPS);
|
||||
|
||||
BMFace *f;
|
||||
BMIter iter;
|
||||
i = 0;
|
||||
|
||||
/*check that all grids are allocated and also set some indices*/
|
||||
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
|
||||
BMIter iter2;
|
||||
BMLoop *l;
|
||||
|
||||
f->head.index = i;
|
||||
|
||||
BM_ITER_ELEM (l, &iter2, f, BM_LOOPS_OF_FACE) {
|
||||
MDisps *mdisp = BM_ELEM_CD_GET_VOID_P(l, cd_disp_off);
|
||||
|
||||
/* allocate new disps, this can happen with newly created faces */
|
||||
if (!mdisp->disps) {
|
||||
multires_reallocate_mdisps(1, mdisp, mmd->totlvl);
|
||||
}
|
||||
|
||||
l->head.index = i;
|
||||
|
||||
if (f->len != 4) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (f->len == 4) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// do the space conversion
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BLI_parallel_range_settings_defaults(&settings);
|
||||
settings.min_iter_per_thread = CCG_TASK_LIMIT;
|
||||
|
||||
MultiresThreadedData data = {
|
||||
.bmop = mode,
|
||||
.sd = sd,
|
||||
.lvl = mmd->totlvl,
|
||||
.bm = bm,
|
||||
.cd_mdisps_off = cd_disp_off,
|
||||
.gridSize = gridSize,
|
||||
};
|
||||
|
||||
BLI_task_parallel_range(0, totpoly, &data, multires_bmesh_space_set_cb, &settings);
|
||||
|
||||
BKE_mesh_free_data_for_undo(me);
|
||||
BKE_subdiv_free(sd);
|
||||
|
||||
bm->elem_index_dirty |= BM_FACE | BM_LOOP;
|
||||
bm->elem_table_dirty |= BM_FACE | BM_LOOP;
|
||||
}
|
||||
|
||||
static void multires_disp_run_cb(void *__restrict userdata,
|
||||
const int pidx,
|
||||
const TaskParallelTLS *__restrict UNUSED(tls))
|
||||
@@ -1218,7 +1673,7 @@ void multires_stitch_grids(Object *ob)
|
||||
int num_faces;
|
||||
BKE_pbvh_get_grid_updates(pbvh, false, (void ***)&faces, &num_faces);
|
||||
if (num_faces) {
|
||||
BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, faces, num_faces);
|
||||
// XXX BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, faces, num_faces);
|
||||
MEM_freeN(faces);
|
||||
}
|
||||
}
|
||||
@@ -1334,7 +1789,7 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
|
||||
|
||||
urat = u - x;
|
||||
vrat = v - y;
|
||||
uopp = 1 - urat;
|
||||
uopp = 1.0f - urat;
|
||||
|
||||
mul_v3_v3fl(d[0], disps[y * st + x], uopp);
|
||||
mul_v3_v3fl(d[1], disps[y * st + x2], urat);
|
||||
@@ -1343,7 +1798,7 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
|
||||
|
||||
add_v3_v3v3(d2[0], d[0], d[1]);
|
||||
add_v3_v3v3(d2[1], d[2], d[3]);
|
||||
mul_v3_fl(d2[0], 1 - vrat);
|
||||
mul_v3_fl(d2[0], 1.0f - vrat);
|
||||
mul_v3_fl(d2[1], vrat);
|
||||
|
||||
add_v3_v3v3(out, d2[0], d2[1]);
|
||||
|
@@ -292,6 +292,12 @@ void multiresModifier_base_apply(struct Depsgraph *depsgraph,
|
||||
multires_reshape_apply_base_update_mesh_coords(&reshape_context);
|
||||
multires_reshape_apply_base_refit_base_mesh(&reshape_context);
|
||||
|
||||
/**
|
||||
* Tag update so deform modifiers (e.g. smooth corrective)
|
||||
* get updated original coordinates
|
||||
*/
|
||||
DEG_id_tag_update((ID *)object, ID_RECALC_GEOMETRY);
|
||||
|
||||
/* Reshape to the stored final state.
|
||||
* Not that the base changed, so the subdiv is to be refined to the new positions. Unfortunately,
|
||||
* this can not be done foe entirely cheap: if there were deformation modifiers prior to the
|
||||
|
@@ -87,11 +87,14 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
|
||||
int *pmap_mem;
|
||||
BKE_mesh_vert_poly_map_create(&pmap,
|
||||
&pmap_mem,
|
||||
base_mesh->mvert,
|
||||
base_mesh->medge,
|
||||
base_mesh->mpoly,
|
||||
base_mesh->mloop,
|
||||
base_mesh->totvert,
|
||||
base_mesh->totpoly,
|
||||
base_mesh->totloop);
|
||||
base_mesh->totloop,
|
||||
false);
|
||||
|
||||
float(*origco)[3] = MEM_calloc_arrayN(
|
||||
base_mesh->totvert, sizeof(float[3]), "multires apply base origco");
|
||||
|
@@ -48,6 +48,39 @@
|
||||
#include "atomic_ops.h"
|
||||
#include "subdiv_converter.h"
|
||||
|
||||
|
||||
bool debug_invert_m3_m3(float m1[3][3], const float m2[3][3], const char *func, int line)
|
||||
{
|
||||
float det;
|
||||
int a, b;
|
||||
bool success;
|
||||
|
||||
/* calc adjoint */
|
||||
adjoint_m3_m3(m1, m2);
|
||||
|
||||
/* then determinant old matrix! */
|
||||
det = determinant_m3_array(m2);
|
||||
|
||||
if (det > -0.0001 && det < 0.0001) {
|
||||
fprintf(stderr, "matrix inverse error %s:%i\n\n", func, line);
|
||||
}
|
||||
|
||||
success = (det != 0.0f);
|
||||
|
||||
if (LIKELY(det != 0.0f)) {
|
||||
det = 1.0f / det;
|
||||
for (a = 0; a < 3; a++) {
|
||||
for (b = 0; b < 3; b++) {
|
||||
m1[a][b] *= det;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//#define invert_m3_m3(m1, m2) debug_invert_m3_m3(m1, m2, __func__, __LINE__)
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Local Structs
|
||||
* \{ */
|
||||
|
@@ -315,6 +315,8 @@ void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_contex
|
||||
|
||||
void multires_reshape_context_free(MultiresReshapeContext *reshape_context)
|
||||
{
|
||||
ModifierData *md;
|
||||
|
||||
if (reshape_context->need_free_subdiv) {
|
||||
BKE_subdiv_free(reshape_context->subdiv);
|
||||
}
|
||||
|
@@ -881,7 +881,8 @@ static BMesh *get_bmesh_from_mesh(Mesh *mesh)
|
||||
.use_toolflags = true,
|
||||
}));
|
||||
|
||||
BM_mesh_bm_from_me(bm,
|
||||
BM_mesh_bm_from_me(NULL,
|
||||
bm,
|
||||
mesh,
|
||||
(&(struct BMeshFromMeshParams){
|
||||
.calc_face_normal = true,
|
||||
@@ -1151,6 +1152,7 @@ bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context)
|
||||
/* Store the new base-mesh as a mesh in context, free bmesh. */
|
||||
context->base_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0);
|
||||
BM_mesh_bm_to_me(NULL,
|
||||
NULL,
|
||||
bm_base_mesh,
|
||||
context->base_mesh,
|
||||
(&(struct BMeshToMeshParams){
|
||||
|
@@ -51,6 +51,7 @@
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_crazyspace.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_gpencil.h"
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_image.h"
|
||||
@@ -67,6 +68,7 @@
|
||||
#include "BKE_pbvh.h"
|
||||
#include "BKE_subdiv_ccg.h"
|
||||
#include "BKE_subsurf.h"
|
||||
#include "BKE_undo_system.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
@@ -77,6 +79,15 @@
|
||||
|
||||
#include "bmesh.h"
|
||||
|
||||
// XXX todo: figure out bad cross module refs
|
||||
void SCULPT_dynamic_topology_sync_layers(Object *ob, Mesh *me);
|
||||
void SCULPT_on_sculptsession_bmesh_free(SculptSession *ss);
|
||||
void SCULPT_dyntopo_node_layers_add(SculptSession *ss);
|
||||
BMesh *SCULPT_dyntopo_empty_bmesh();
|
||||
void SCULPT_undo_ensure_bmlog(Object *ob);
|
||||
|
||||
static void init_mdyntopo_layer(SculptSession *ss, int totvert);
|
||||
|
||||
static void palette_init_data(ID *id)
|
||||
{
|
||||
Palette *palette = (Palette *)id;
|
||||
@@ -1075,7 +1086,8 @@ bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
|
||||
paint->symmetry_flags |= PAINT_SYMM_X;
|
||||
|
||||
/* Make sure at least dyntopo subdivision is enabled */
|
||||
data->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
|
||||
data->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE | SCULPT_DYNTOPO_CLEANUP |
|
||||
SCULPT_DYNTOPO_ENABLED;
|
||||
}
|
||||
else if ((GpPaint **)r_paint == &ts->gp_paint) {
|
||||
GpPaint *data = MEM_callocN(sizeof(*data), __func__);
|
||||
@@ -1375,20 +1387,23 @@ static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
|
||||
|
||||
if (ss->bm) {
|
||||
if (ob->data) {
|
||||
BMIter iter;
|
||||
BMFace *efa;
|
||||
BM_ITER_MESH (efa, &iter, ss->bm, BM_FACES_OF_MESH) {
|
||||
BM_elem_flag_set(efa, BM_ELEM_SMOOTH, ss->bm_smooth_shading);
|
||||
}
|
||||
if (reorder) {
|
||||
BM_log_mesh_elems_reorder(ss->bm, ss->bm_log);
|
||||
}
|
||||
BM_mesh_bm_to_me(NULL,
|
||||
ss->bm,
|
||||
ob->data,
|
||||
(&(struct BMeshToMeshParams){
|
||||
.calc_object_remap = false,
|
||||
}));
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
|
||||
BM_mesh_bm_to_me(
|
||||
NULL,
|
||||
NULL,
|
||||
ss->bm,
|
||||
ob->data,
|
||||
(&(struct BMeshToMeshParams){.calc_object_remap = false,
|
||||
/*
|
||||
for memfile undo steps we need to
|
||||
save id and temporary layers
|
||||
*/
|
||||
.copy_temp_cdlayers = true,
|
||||
.ignore_mesh_id_layers = false,
|
||||
.cd_mask_extra = CD_MASK_MESH_ID | CD_MASK_DYNTOPO_VERT
|
||||
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1427,6 +1442,7 @@ static void sculptsession_free_pbvh(Object *object)
|
||||
MEM_SAFE_FREE(ss->vemap_mem);
|
||||
|
||||
MEM_SAFE_FREE(ss->persistent_base);
|
||||
MEM_SAFE_FREE(ss->limit_surface);
|
||||
|
||||
MEM_SAFE_FREE(ss->preview_vert_index_list);
|
||||
ss->preview_vert_index_count = 0;
|
||||
@@ -1435,6 +1451,7 @@ static void sculptsession_free_pbvh(Object *object)
|
||||
|
||||
MEM_SAFE_FREE(ss->vertex_info.connected_component);
|
||||
MEM_SAFE_FREE(ss->vertex_info.boundary);
|
||||
MEM_SAFE_FREE(ss->vertex_info.symmetrize_map);
|
||||
|
||||
MEM_SAFE_FREE(ss->fake_neighbors.fake_neighbor_index);
|
||||
}
|
||||
@@ -1466,7 +1483,19 @@ void BKE_sculptsession_free(Object *ob)
|
||||
if (ob && ob->sculpt) {
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
if (ss->mdyntopo_verts) {
|
||||
MEM_freeN(ss->mdyntopo_verts);
|
||||
ss->mdyntopo_verts = NULL;
|
||||
}
|
||||
|
||||
if (ss->bm_log && BM_log_free(ss->bm_log, true)) {
|
||||
ss->bm_log = NULL;
|
||||
}
|
||||
|
||||
/*try to save current mesh*/
|
||||
if (ss->bm) {
|
||||
SCULPT_on_sculptsession_bmesh_free(ss);
|
||||
|
||||
BKE_sculptsession_bm_to_me(ob, true);
|
||||
BM_mesh_free(ss->bm);
|
||||
}
|
||||
@@ -1482,10 +1511,6 @@ void BKE_sculptsession_free(Object *ob)
|
||||
MEM_SAFE_FREE(ss->vemap);
|
||||
MEM_SAFE_FREE(ss->vemap_mem);
|
||||
|
||||
if (ss->bm_log) {
|
||||
BM_log_free(ss->bm_log);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(ss->texcache);
|
||||
|
||||
if (ss->tex_pool) {
|
||||
@@ -1496,6 +1521,8 @@ void BKE_sculptsession_free(Object *ob)
|
||||
MEM_SAFE_FREE(ss->deform_cos);
|
||||
MEM_SAFE_FREE(ss->deform_imats);
|
||||
|
||||
MEM_SAFE_FREE(ss->limit_surface);
|
||||
|
||||
if (ss->pose_ik_chain_preview) {
|
||||
for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) {
|
||||
MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments[i].weights);
|
||||
@@ -1608,6 +1635,12 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
|
||||
return false;
|
||||
}
|
||||
|
||||
char BKE_get_fset_boundary_symflag(Object *object)
|
||||
{
|
||||
const Mesh *mesh = BKE_mesh_from_object(object);
|
||||
return mesh->flag & ME_SCULPT_MIRROR_FSET_BOUNDARIES ? mesh->symmetry : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param need_mask: So that the evaluated mesh that is returned has mask data.
|
||||
*/
|
||||
@@ -1621,7 +1654,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
||||
Sculpt *sd = scene->toolsettings->sculpt;
|
||||
SculptSession *ss = ob->sculpt;
|
||||
const Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
|
||||
const bool use_face_sets = (ob->mode & OB_MODE_SCULPT) != 0;
|
||||
|
||||
@@ -1645,6 +1678,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
||||
}
|
||||
|
||||
ss->shapekey_active = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
|
||||
ss->boundary_symmetry = (int)BKE_get_fset_boundary_symflag(ob);
|
||||
|
||||
/* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path,
|
||||
* so no extra checks is needed here. */
|
||||
@@ -1659,14 +1693,16 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
||||
/* These are assigned to the base mesh in Multires. This is needed because Face Sets operators
|
||||
* and tools use the Face Sets data from the base mesh when Multires is active. */
|
||||
ss->mvert = me->mvert;
|
||||
ss->mpoly = me->mpoly;
|
||||
ss->medge = me->medge;
|
||||
ss->mloop = me->mloop;
|
||||
ss->mpoly = me->mpoly;
|
||||
}
|
||||
else {
|
||||
ss->totvert = me->totvert;
|
||||
ss->totpoly = me->totpoly;
|
||||
ss->totfaces = me->totpoly;
|
||||
ss->mvert = me->mvert;
|
||||
ss->medge = me->medge;
|
||||
ss->mpoly = me->mpoly;
|
||||
ss->mloop = me->mloop;
|
||||
ss->multires.active = false;
|
||||
@@ -1674,6 +1710,11 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
||||
ss->multires.level = 0;
|
||||
ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
|
||||
ss->vcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
|
||||
|
||||
ss->vdata = &me->vdata;
|
||||
ss->edata = &me->edata;
|
||||
ss->ldata = &me->ldata;
|
||||
ss->pdata = &me->pdata;
|
||||
}
|
||||
|
||||
/* Sculpt Face Sets. */
|
||||
@@ -1686,8 +1727,10 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
||||
}
|
||||
|
||||
ss->subdiv_ccg = me_eval->runtime.subdiv_ccg;
|
||||
ss->fast_draw = (scene->toolsettings->sculpt->flags & SCULPT_FAST_DRAW) != 0;
|
||||
|
||||
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
|
||||
|
||||
BLI_assert(pbvh == ss->pbvh);
|
||||
UNUSED_VARS_NDEBUG(pbvh);
|
||||
|
||||
@@ -1697,8 +1740,16 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
||||
BKE_pbvh_face_sets_color_set(ss->pbvh, me->face_sets_color_seed, me->face_sets_color_default);
|
||||
|
||||
if (need_pmap && ob->type == OB_MESH && !ss->pmap) {
|
||||
BKE_mesh_vert_poly_map_create(
|
||||
&ss->pmap, &ss->pmap_mem, me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
|
||||
BKE_mesh_vert_poly_map_create(&ss->pmap,
|
||||
&ss->pmap_mem,
|
||||
me->mvert,
|
||||
me->medge,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->totvert,
|
||||
me->totpoly,
|
||||
me->totloop,
|
||||
false);
|
||||
}
|
||||
|
||||
pbvh_show_mask_set(ss->pbvh, ss->show_mask);
|
||||
@@ -1757,8 +1808,8 @@ void BKE_sculpt_update_object_before_eval(Object *ob)
|
||||
/* Update before mesh evaluation in the dependency graph. */
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
if (ss && ss->building_vp_handle == false) {
|
||||
if (!ss->cache && !ss->filter_cache && !ss->expand_cache) {
|
||||
if (ss && (ss->building_vp_handle == false || ss->needs_pbvh_rebuild)) {
|
||||
if (ss->needs_pbvh_rebuild || (!ss->cache && !ss->filter_cache && !ss->expand_cache)) {
|
||||
/* We free pbvh on changes, except in the middle of drawing a stroke
|
||||
* since it can't deal with changing PVBH node organization, we hope
|
||||
* topology does not change in the meantime .. weak. */
|
||||
@@ -1793,6 +1844,7 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval)
|
||||
|
||||
BLI_assert(me_eval != NULL);
|
||||
sculpt_update_object(depsgraph, ob_orig, me_eval, false, false, false);
|
||||
SCULPT_dynamic_topology_sync_layers(ob_orig, me_eval);
|
||||
}
|
||||
|
||||
void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
|
||||
@@ -1809,19 +1861,21 @@ void BKE_sculpt_color_layer_create_if_needed(struct Object *object)
|
||||
CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert);
|
||||
BKE_mesh_update_customdata_pointers(orig_me, true);
|
||||
DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY_ALL_MODES);
|
||||
SCULPT_dynamic_topology_sync_layers(object, orig_me);
|
||||
}
|
||||
|
||||
/** \warning Expects a fully evaluated depsgraph. */
|
||||
void BKE_sculpt_update_object_for_edit(
|
||||
Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool need_mask, bool need_colors)
|
||||
{
|
||||
/* Update from sculpt operators and undo, to update sculpt session
|
||||
* and PBVH after edits. */
|
||||
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
|
||||
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_orig);
|
||||
Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
|
||||
|
||||
BLI_assert(ob_orig == DEG_get_original_object(ob_orig));
|
||||
|
||||
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_orig);
|
||||
Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
|
||||
BLI_assert(me_eval != NULL);
|
||||
|
||||
sculpt_update_object(depsgraph, ob_orig, me_eval, need_pmap, need_mask, need_colors);
|
||||
sculpt_update_object(depsgraph, ob_orig, me_eval, true, need_mask, need_colors);
|
||||
}
|
||||
|
||||
int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
|
||||
@@ -1896,11 +1950,30 @@ void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene)
|
||||
|
||||
Sculpt *sd = scene->toolsettings->sculpt;
|
||||
if (!sd->detail_size) {
|
||||
sd->detail_size = 12;
|
||||
sd->detail_size = 8.0f;
|
||||
}
|
||||
|
||||
if (!sd->dyntopo_radius_scale) {
|
||||
sd->dyntopo_radius_scale = 1.0f;
|
||||
}
|
||||
|
||||
// we check these flags here in case versioning code fails
|
||||
if (!sd->detail_range || !sd->dyntopo_spacing) {
|
||||
sd->flags |= SCULPT_DYNTOPO_CLEANUP | SCULPT_DYNTOPO_ENABLED;
|
||||
}
|
||||
|
||||
if (!sd->detail_range) {
|
||||
sd->detail_range = 0.4f;
|
||||
}
|
||||
|
||||
if (!sd->detail_percent) {
|
||||
sd->detail_percent = 25;
|
||||
}
|
||||
|
||||
if (!sd->dyntopo_spacing) {
|
||||
sd->dyntopo_spacing = 35;
|
||||
}
|
||||
|
||||
if (sd->constant_detail == 0.0f) {
|
||||
sd->constant_detail = 3.0f;
|
||||
}
|
||||
@@ -2094,14 +2167,21 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
|
||||
static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
|
||||
{
|
||||
PBVH *pbvh = BKE_pbvh_new();
|
||||
|
||||
BKE_pbvh_set_symmetry(pbvh, 0, (int)BKE_get_fset_boundary_symflag(ob));
|
||||
|
||||
BKE_pbvh_build_bmesh(pbvh,
|
||||
ob->sculpt->bm,
|
||||
ob->sculpt->bm_smooth_shading,
|
||||
ob->sculpt->bm_log,
|
||||
ob->sculpt->cd_vert_node_offset,
|
||||
ob->sculpt->cd_face_node_offset);
|
||||
ob->sculpt->cd_face_node_offset,
|
||||
ob->sculpt->cd_dyn_vert,
|
||||
ob->sculpt->cd_face_areas,
|
||||
ob->sculpt->fast_draw);
|
||||
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
|
||||
pbvh_show_face_sets_set(pbvh, false);
|
||||
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
@@ -2118,17 +2198,21 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
|
||||
|
||||
BKE_sculpt_sync_face_set_visibility(me, NULL);
|
||||
|
||||
BKE_sculptsession_check_mdyntopo(ob->sculpt, me->totvert);
|
||||
|
||||
BKE_pbvh_build_mesh(pbvh,
|
||||
me,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->mvert,
|
||||
ob->sculpt->mdyntopo_verts,
|
||||
me->totvert,
|
||||
&me->vdata,
|
||||
&me->ldata,
|
||||
&me->pdata,
|
||||
looptri,
|
||||
looptris_num);
|
||||
looptris_num,
|
||||
ob->sculpt->fast_draw);
|
||||
|
||||
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
|
||||
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
|
||||
@@ -2160,18 +2244,50 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
|
||||
&key,
|
||||
(void **)subdiv_ccg->grid_faces,
|
||||
subdiv_ccg->grid_flag_mats,
|
||||
subdiv_ccg->grid_hidden);
|
||||
subdiv_ccg->grid_hidden,
|
||||
ob->sculpt->fast_draw);
|
||||
|
||||
BKE_sculptsession_check_mdyntopo(ob->sculpt, BKE_pbvh_get_grid_num_vertices(pbvh));
|
||||
|
||||
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
|
||||
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert)
|
||||
{
|
||||
if (!ss->bm && (!ss->mdyntopo_verts || totvert != ss->mdyntopo_verts_size)) {
|
||||
init_mdyntopo_layer(ss, totvert);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void init_mdyntopo_layer(SculptSession *ss, int totvert)
|
||||
{
|
||||
if (ss->mdyntopo_verts) {
|
||||
MEM_freeN(ss->mdyntopo_verts);
|
||||
}
|
||||
|
||||
ss->mdyntopo_verts = MEM_calloc_arrayN(totvert, sizeof(*ss->mdyntopo_verts), "mdyntopo_verts");
|
||||
ss->mdyntopo_verts_size = totvert;
|
||||
|
||||
MDynTopoVert *mv = ss->mdyntopo_verts;
|
||||
|
||||
for (int i = 0; i < totvert; i++, mv++) {
|
||||
mv->flag = DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT;
|
||||
mv->stroke_id = -1;
|
||||
}
|
||||
}
|
||||
PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
||||
{
|
||||
if (ob == NULL || ob->sculpt == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Scene *scene = DEG_get_input_scene(depsgraph);
|
||||
|
||||
bool respect_hide = true;
|
||||
if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
|
||||
if (!(BKE_paint_select_vert_test(ob) || BKE_paint_select_face_test(ob))) {
|
||||
@@ -2181,6 +2297,8 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
||||
|
||||
PBVH *pbvh = ob->sculpt->pbvh;
|
||||
if (pbvh != NULL) {
|
||||
SCULPT_update_flat_vcol_shading(ob, scene);
|
||||
|
||||
/* NOTE: It is possible that grids were re-allocated due to modifier
|
||||
* stack. Need to update those pointers. */
|
||||
if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
|
||||
@@ -2191,14 +2309,59 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
||||
BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg);
|
||||
}
|
||||
}
|
||||
else if (BKE_pbvh_type(pbvh) == PBVH_BMESH) {
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
|
||||
SCULPT_dynamic_topology_sync_layers(ob, BKE_object_get_original_mesh(ob));
|
||||
}
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
if (ob->sculpt->bm != NULL) {
|
||||
/* Sculpting on a BMesh (dynamic-topology) gets a special PBVH. */
|
||||
pbvh = build_pbvh_for_dynamic_topology(ob);
|
||||
|
||||
ob->sculpt->pbvh = pbvh;
|
||||
}
|
||||
else {
|
||||
#if 1 // def WHEN_GLOBAL_UNDO_WORKS
|
||||
/*detect if we are loading from an undo memfile step*/
|
||||
Mesh *mesh_orig = BKE_object_get_original_mesh(ob);
|
||||
bool is_dyntopo = (mesh_orig->flag & ME_SCULPT_DYNAMIC_TOPOLOGY);
|
||||
|
||||
if (is_dyntopo) {
|
||||
BMesh *bm = SCULPT_dyntopo_empty_bmesh();
|
||||
|
||||
ob->sculpt->bm = bm;
|
||||
|
||||
BM_mesh_bm_from_me(NULL,
|
||||
bm,
|
||||
mesh_orig,
|
||||
(&(struct BMeshFromMeshParams){.calc_face_normal = true,
|
||||
.use_shapekey = true,
|
||||
.active_shapekey = ob->shapenr,
|
||||
.ignore_id_layers = false,
|
||||
.copy_temp_cdlayers = true,
|
||||
.cd_mask_extra = CD_MASK_DYNTOPO_VERT}));
|
||||
|
||||
SCULPT_dyntopo_node_layers_add(ob->sculpt);
|
||||
|
||||
SCULPT_undo_ensure_bmlog(ob);
|
||||
|
||||
pbvh = build_pbvh_for_dynamic_topology(ob);
|
||||
}
|
||||
else {
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *mesh_eval = object_eval->data;
|
||||
if (mesh_eval->runtime.subdiv_ccg != NULL) {
|
||||
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime.subdiv_ccg, respect_hide);
|
||||
}
|
||||
else if (ob->type == OB_MESH) {
|
||||
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
|
||||
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
|
||||
}
|
||||
}
|
||||
#else
|
||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
Mesh *mesh_eval = object_eval->data;
|
||||
if (mesh_eval->runtime.subdiv_ccg != NULL) {
|
||||
@@ -2206,11 +2369,20 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
||||
}
|
||||
else if (ob->type == OB_MESH) {
|
||||
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;
|
||||
|
||||
BKE_sculptsession_check_mdyntopo(ob->sculpt, me_eval_deform->totvert);
|
||||
|
||||
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform, respect_hide);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ob->sculpt->pbvh = pbvh;
|
||||
|
||||
if (pbvh) {
|
||||
SCULPT_update_flat_vcol_shading(ob, scene);
|
||||
}
|
||||
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
@@ -2232,6 +2404,12 @@ bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const View3D *v3d)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
|
||||
return !(v3d && (v3d->shading.type > OB_SOLID));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
|
||||
/* Regular mesh only draws from PBVH without modifiers and shape keys. */
|
||||
const bool full_shading = (v3d && (v3d->shading.type > OB_SOLID));
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
31
source/blender/blenkernel/intern/pbvh_cache_test_main.c
Normal file
31
source/blender/blenkernel/intern/pbvh_cache_test_main.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_pbvh.h"
|
||||
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
#include "pbvh_intern.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// void pbvh_bmesh_do_cache_test(void);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
printf("argc: %d\n", argc);
|
||||
|
||||
// pbvh_bmesh_do_cache_test();
|
||||
|
||||
return 0;
|
||||
}
|
266
source/blender/blenkernel/intern/pbvh_displacement.c
Normal file
266
source/blender/blenkernel/intern/pbvh_displacement.c
Normal file
@@ -0,0 +1,266 @@
|
||||
#if 0
|
||||
# include "MEM_guardedalloc.h"
|
||||
|
||||
# include "BLI_alloca.h"
|
||||
# include "BLI_array.h"
|
||||
# include "BLI_compiler_attrs.h"
|
||||
# include "BLI_compiler_compat.h"
|
||||
# include "BLI_ghash.h"
|
||||
# include "BLI_linklist.h"
|
||||
# include "BLI_math.h"
|
||||
# include "BLI_memarena.h"
|
||||
# include "BLI_memblock.h"
|
||||
# include "BLI_mempool.h"
|
||||
# include "BLI_utildefines.h"
|
||||
|
||||
# include "BLI_hash.h"
|
||||
|
||||
# include "BKE_context.h"
|
||||
# include "BKE_global.h"
|
||||
# include "BKE_image.h"
|
||||
# include "BKE_mesh.h"
|
||||
# include "BKE_multires.h"
|
||||
# include "BKE_object.h"
|
||||
# include "BKE_pbvh.h"
|
||||
# include "BKE_scene.h"
|
||||
|
||||
# include "BLI_bitmap.h"
|
||||
# include "DNA_customdata_types.h"
|
||||
# include "DNA_image_types.h"
|
||||
# include "DNA_material_types.h"
|
||||
# include "DNA_mesh_types.h"
|
||||
# include "DNA_meshdata_types.h"
|
||||
# include "DNA_object_types.h"
|
||||
# include "DNA_scene_types.h"
|
||||
|
||||
# include "pbvh_intern.h"
|
||||
|
||||
# include "bmesh.h"
|
||||
|
||||
void *BKE_pbvh_get_tex_settings(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm)
|
||||
{
|
||||
return NULL; // implement me!
|
||||
}
|
||||
|
||||
void *BKE_pbvh_get_tex_data(PBVH *pbvh, PBVHNode *node, TexPointRef vdm)
|
||||
{
|
||||
return NULL; // implement me!
|
||||
}
|
||||
|
||||
typedef union TexelKey {
|
||||
struct {
|
||||
int idx; // index in image
|
||||
int co_key; // used to differentiate same texel used in different 3d points in space
|
||||
} key;
|
||||
intptr_t i;
|
||||
} TexelKey;
|
||||
|
||||
BLI_INLINE int calc_co_key(const float *co)
|
||||
{
|
||||
const int mul = 65535;
|
||||
const int mask = 65535;
|
||||
|
||||
int x = (int)co[0] + (((int)co[0] * mul) & mask);
|
||||
int y = (int)co[0] + (((int)co[0] * mul) & mask);
|
||||
int z = (int)co[0] + (((int)co[0] * mul) & mask);
|
||||
|
||||
return BLI_hash_int_3d(x, y, z);
|
||||
}
|
||||
|
||||
typedef struct TextureVDMSettings {
|
||||
ImageUser ima_user;
|
||||
ID *image;
|
||||
bool tangent_space;
|
||||
|
||||
char uv_layer[64];
|
||||
|
||||
// used by texture_vdm_get_points
|
||||
// BLI_bitmap *texel_used_map;
|
||||
GSet *texel_used_map;
|
||||
|
||||
int width, height;
|
||||
bool invalid;
|
||||
} TextureVDMSettings;
|
||||
|
||||
typedef struct TextureNodeData {
|
||||
TexPointRef *point_ids;
|
||||
float (*point_cos)[3];
|
||||
float (*point_uvs)[2];
|
||||
float **point_cos_ptrs;
|
||||
int totpoint;
|
||||
} TextureNodeData;
|
||||
|
||||
void texture_vdm_begin(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm)
|
||||
{
|
||||
TextureVDMSettings *settings = BKE_pbvh_get_tex_settings(pbvh, node, vdm);
|
||||
|
||||
if (!settings->image) {
|
||||
return;
|
||||
}
|
||||
|
||||
Image *image = (Image *)settings->image;
|
||||
|
||||
int w = 0, h = 0;
|
||||
BKE_image_get_size(image, &settings->ima_user, &w, &h);
|
||||
|
||||
// Image *image = settings->image.
|
||||
settings->width = w;
|
||||
settings->height = h;
|
||||
// settings->texel_used_map = BLI_BITMAP_NEW(w * h, "texel_used_map");
|
||||
settings->texel_used_map = BLI_gset_ptr_new("texel_used_map");
|
||||
}
|
||||
|
||||
void texture_vdm_build_points(PBVH *pbvh, PBVHNode *node, TexLayerRef vdm)
|
||||
{
|
||||
TextureVDMSettings *settings = BKE_pbvh_get_tex_settings(pbvh, node, vdm);
|
||||
TextureNodeData *data = BKE_pbvh_get_tex_data(pbvh, node, vdm);
|
||||
|
||||
int idx;
|
||||
|
||||
if (!settings->uv_layer[0]) {
|
||||
idx = CustomData_get_layer_index(&pbvh->bm->ldata, CD_MLOOPUV);
|
||||
}
|
||||
else {
|
||||
idx = CustomData_get_named_layer_index(&pbvh->bm->ldata, CD_MLOOPUV, settings->uv_layer);
|
||||
}
|
||||
|
||||
if (idx < 0) {
|
||||
settings->invalid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const int cd_uv = pbvh->bm->ldata.layers[idx].offset;
|
||||
const int w = settings->width, h = settings->height;
|
||||
|
||||
float **point_cos_ptrs = NULL;
|
||||
float *uvs = NULL;
|
||||
float *cos = NULL;
|
||||
TexPointRef *ids = NULL;
|
||||
|
||||
BLI_array_declare(point_cos_ptrs);
|
||||
BLI_array_declare(uvs);
|
||||
BLI_array_declare(cos);
|
||||
BLI_array_declare(ids);
|
||||
|
||||
for (int i = 0; i < node->tribuf->tottri; i++) {
|
||||
PBVHTri *tri = node->tribuf->tris + i;
|
||||
|
||||
BMLoop *ls[3] = {(BMLoop *)tri->l[0], (BMLoop *)tri->l[1], (BMLoop *)tri->l[2]};
|
||||
float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {FLT_MIN, FLT_MIN};
|
||||
|
||||
float tricos[3][3];
|
||||
|
||||
copy_v3_v3(tricos[0], ls[0]->v->co);
|
||||
copy_v3_v3(tricos[1], ls[1]->v->co);
|
||||
copy_v3_v3(tricos[2], ls[2]->v->co);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(ls[j], cd_uv);
|
||||
minmax_v2v2_v2(min, max, luv->uv);
|
||||
}
|
||||
|
||||
int dw = (int)((max[0] - min[0]) * (float)w + 0.000001f);
|
||||
int dh = (int)((max[1] - min[1]) * (float)h + 0.000001f);
|
||||
|
||||
dw = MAX2(dw, 1);
|
||||
dh = MAX2(dh, 1);
|
||||
|
||||
float du = (max[0] - min[0]) / dw;
|
||||
float dv = (max[1] - min[1]) / dh;
|
||||
|
||||
float u = min[0], v = min[1];
|
||||
for (int y = 0; y < dh; y++, v += dv) {
|
||||
u = min[0];
|
||||
|
||||
for (int x = 0; x < dw; x++, u += du) {
|
||||
int idx = y * w + x;
|
||||
float co[3];
|
||||
|
||||
interp_barycentric_tri_v3(tricos, u, v, co);
|
||||
|
||||
TexelKey key;
|
||||
key.key.idx = idx;
|
||||
key.key.co_key = calc_co_key(co);
|
||||
|
||||
if (BLI_gset_haskey(settings->texel_used_map, (void *)key.i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BLI_gset_insert(settings->texel_used_map, (void *)key.i);
|
||||
|
||||
BLI_array_append(uvs, u);
|
||||
BLI_array_append(uvs, v);
|
||||
|
||||
BLI_array_append(cos, co[0]);
|
||||
BLI_array_append(cos, co[1]);
|
||||
BLI_array_append(cos, co[2]);
|
||||
BLI_array_append(ids, (TexPointRef)key.i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settings->invalid = false;
|
||||
MEM_SAFE_FREE(data->point_cos);
|
||||
MEM_SAFE_FREE(data->point_ids);
|
||||
MEM_SAFE_FREE(data->point_uvs);
|
||||
MEM_SAFE_FREE(data->point_cos_ptrs);
|
||||
|
||||
int totpoint = BLI_array_len(ids);
|
||||
|
||||
data->totpoint = totpoint;
|
||||
|
||||
data->point_cos_ptrs = MEM_malloc_arrayN(totpoint, sizeof(void *), "point_cos_ptrs");
|
||||
|
||||
// dumb casting trick
|
||||
union {
|
||||
float *cos;
|
||||
float (*cos3)[3];
|
||||
} castcos;
|
||||
|
||||
union {
|
||||
float *uvs;
|
||||
float (*uvs2)[2];
|
||||
} castuvs;
|
||||
|
||||
castcos.cos = cos;
|
||||
castuvs.uvs = uvs;
|
||||
|
||||
data->point_cos = castcos.cos3;
|
||||
data->point_ids = ids;
|
||||
data->point_uvs = castuvs.uvs2;
|
||||
|
||||
for (int i = 0; i < totpoint; i++) {
|
||||
data->point_cos_ptrs[i] = cos + i * 3;
|
||||
}
|
||||
}
|
||||
|
||||
void texture_vdm_get_points(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
TexLayerRef vdm,
|
||||
TexPointRef **r_ids,
|
||||
float ***r_cos,
|
||||
float ***r_nos,
|
||||
int *r_totpoint)
|
||||
{
|
||||
TextureVDMSettings *settings = BKE_pbvh_get_tex_settings(pbvh, node, vdm);
|
||||
TextureNodeData *data = BKE_pbvh_get_tex_data(pbvh, node, vdm);
|
||||
|
||||
if (r_totpoint) {
|
||||
*r_totpoint = data->totpoint;
|
||||
}
|
||||
|
||||
if (r_cos) {
|
||||
*r_cos = data->point_cos_ptrs;
|
||||
}
|
||||
|
||||
if (r_ids) {
|
||||
*r_ids = data->point_ids;
|
||||
}
|
||||
}
|
||||
|
||||
static SculptDisplacementDef texture_vdm = {
|
||||
.type = SCULPT_TEXTURE_UV,
|
||||
.settings_size = sizeof(TextureNodeData),
|
||||
.getPointsFromNode = texture_vdm_get_points,
|
||||
};
|
||||
#endif
|
@@ -16,9 +16,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
|
||||
#include "bmesh.h"
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*/
|
||||
struct MDynTopoVert;
|
||||
|
||||
/* Axis-aligned bounding box */
|
||||
typedef struct {
|
||||
@@ -35,6 +43,10 @@ typedef struct {
|
||||
struct PBVHNode {
|
||||
/* Opaque handle for drawing code */
|
||||
struct GPU_PBVH_Buffers *draw_buffers;
|
||||
struct GPU_PBVH_Buffers **mat_draw_buffers; // currently only used by pbvh_bmesh
|
||||
int tot_mat_draw_buffers;
|
||||
|
||||
int id;
|
||||
|
||||
/* Voxel bounds */
|
||||
BB vb;
|
||||
@@ -43,6 +55,7 @@ struct PBVHNode {
|
||||
/* For internal nodes, the offset of the children in the PBVH
|
||||
* 'nodes' array. */
|
||||
int children_offset;
|
||||
int subtree_tottri;
|
||||
|
||||
/* Pointer into the PBVH prim_indices array and the number of
|
||||
* primitives used by this leaf node.
|
||||
@@ -86,7 +99,7 @@ struct PBVHNode {
|
||||
|
||||
/* Indicates whether this node is a leaf or not; also used for
|
||||
* marking various updates that need to be applied. */
|
||||
PBVHNodeFlags flag : 16;
|
||||
PBVHNodeFlags flag : 32;
|
||||
|
||||
/* Used for raycasting: how close bb is to the ray point. */
|
||||
float tmin;
|
||||
@@ -98,27 +111,39 @@ struct PBVHNode {
|
||||
PBVHProxyNode *proxies;
|
||||
|
||||
/* Dyntopo */
|
||||
GSet *bm_faces;
|
||||
GSet *bm_unique_verts;
|
||||
GSet *bm_other_verts;
|
||||
float (*bm_orco)[3];
|
||||
int (*bm_ortri)[3];
|
||||
int bm_tot_ortri;
|
||||
TableGSet *bm_faces;
|
||||
TableGSet *bm_unique_verts;
|
||||
TableGSet *bm_other_verts;
|
||||
|
||||
PBVHTriBuf *tribuf; // all triangles
|
||||
PBVHTriBuf *tri_buffers; // tribuffers, one per material used
|
||||
int tot_tri_buffers;
|
||||
|
||||
int updategen;
|
||||
|
||||
/* Used to store the brush color during a stroke and composite it over the original color */
|
||||
PBVHColorBufferNode color_buffer;
|
||||
#ifdef PROXY_ADVANCED
|
||||
ProxyVertArray proxyverts;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PBVH_DYNTOPO_SMOOTH_SHADING = 1,
|
||||
PBVH_FAST_DRAW = 2 // hides facesets/masks and forces smooth to save GPU bandwidth
|
||||
} PBVHFlags;
|
||||
|
||||
typedef struct PBVHBMeshLog PBVHBMeshLog;
|
||||
struct DMFlagMat;
|
||||
|
||||
struct PBVH {
|
||||
PBVHType type;
|
||||
PBVHFlags flags;
|
||||
|
||||
int idgen;
|
||||
|
||||
bool dyntopo_stop;
|
||||
|
||||
PBVHNode *nodes;
|
||||
int node_mem_count, totnode;
|
||||
|
||||
@@ -127,6 +152,7 @@ struct PBVH {
|
||||
int totvert;
|
||||
|
||||
int leaf_limit;
|
||||
int depth_limit;
|
||||
|
||||
/* Mesh data */
|
||||
const struct Mesh *mesh;
|
||||
@@ -146,7 +172,7 @@ struct PBVH {
|
||||
CCGKey gridkey;
|
||||
CCGElem **grids;
|
||||
void **gridfaces;
|
||||
const DMFlagMat *grid_flag_mats;
|
||||
const struct DMFlagMat *grid_flag_mats;
|
||||
int totgrid;
|
||||
BLI_bitmap **grid_hidden;
|
||||
|
||||
@@ -168,14 +194,31 @@ struct PBVH {
|
||||
BMesh *bm;
|
||||
float bm_max_edge_len;
|
||||
float bm_min_edge_len;
|
||||
float bm_detail_range;
|
||||
|
||||
int cd_dyn_vert;
|
||||
int cd_vert_node_offset;
|
||||
int cd_face_node_offset;
|
||||
int cd_vert_mask_offset;
|
||||
int cd_vcol_offset;
|
||||
int cd_faceset_offset;
|
||||
int cd_face_area;
|
||||
|
||||
float planes[6][4];
|
||||
int num_planes;
|
||||
|
||||
int symmetry;
|
||||
int boundary_symmetry;
|
||||
|
||||
struct BMLog *bm_log;
|
||||
struct SubdivCCG *subdiv_ccg;
|
||||
|
||||
bool flat_vcol_shading;
|
||||
bool need_full_render; // used by pbvh drawing for PBVH_BMESH
|
||||
|
||||
int balance_counter;
|
||||
int stroke_id; // used to keep origdata up to date in PBVH_BMESH
|
||||
struct MDynTopoVert *mdyntopo_verts;
|
||||
};
|
||||
|
||||
/* pbvh.c */
|
||||
@@ -184,6 +227,9 @@ void BB_expand(BB *bb, const float co[3]);
|
||||
void BB_expand_with_bb(BB *bb, BB *bb2);
|
||||
void BBC_update_centroid(BBC *bbc);
|
||||
int BB_widest_axis(const BB *bb);
|
||||
void BB_intersect(BB *r_out, BB *a, BB *b);
|
||||
float BB_volume(const BB *bb);
|
||||
|
||||
void pbvh_grow_nodes(PBVH *bvh, int totnode);
|
||||
bool ray_face_intersection_quad(const float ray_start[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
@@ -217,20 +263,97 @@ bool ray_face_nearest_tri(const float ray_start[3],
|
||||
|
||||
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag);
|
||||
|
||||
bool ray_face_intersection_depth_tri(const float ray_start[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
const float t0[3],
|
||||
const float t1[3],
|
||||
const float t2[3],
|
||||
float *r_depth,
|
||||
float *r_back_depth,
|
||||
int *hit_count);
|
||||
|
||||
/* pbvh_bmesh.c */
|
||||
bool pbvh_bmesh_node_raycast(PBVHNode *node,
|
||||
bool pbvh_bmesh_node_raycast(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
float *dist,
|
||||
int *hit_count,
|
||||
float *depth,
|
||||
float *back_depth,
|
||||
bool use_original,
|
||||
int *r_active_vertex_index,
|
||||
float *r_face_normal);
|
||||
bool pbvh_bmesh_node_nearest_to_ray(PBVHNode *node,
|
||||
SculptVertRef *r_active_vertex_index,
|
||||
SculptFaceRef *r_active_face_index,
|
||||
float *r_face_normal,
|
||||
int stroke_id);
|
||||
|
||||
bool pbvh_bmesh_node_nearest_to_ray(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
float *depth,
|
||||
float *dist_sq,
|
||||
bool use_original);
|
||||
bool use_original,
|
||||
int stroke_id);
|
||||
|
||||
void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
|
||||
|
||||
void pbvh_free_all_draw_buffers(PBVHNode *node);
|
||||
void pbvh_update_free_all_draw_buffers(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
BLI_INLINE int pbvh_bmesh_node_index_from_vert(PBVH *pbvh, const BMVert *key)
|
||||
{
|
||||
const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_vert_node_offset);
|
||||
BLI_assert(node_index != DYNTOPO_NODE_NONE);
|
||||
BLI_assert(node_index < pbvh->totnode);
|
||||
return node_index;
|
||||
}
|
||||
|
||||
BLI_INLINE int pbvh_bmesh_node_index_from_face(PBVH *pbvh, const BMFace *key)
|
||||
{
|
||||
const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_face_node_offset);
|
||||
BLI_assert(node_index != DYNTOPO_NODE_NONE);
|
||||
BLI_assert(node_index < pbvh->totnode);
|
||||
return node_index;
|
||||
}
|
||||
|
||||
BLI_INLINE PBVHNode *pbvh_bmesh_node_from_vert(PBVH *pbvh, const BMVert *key)
|
||||
{
|
||||
int ni = pbvh_bmesh_node_index_from_vert(pbvh, key);
|
||||
|
||||
return ni >= 0 ? pbvh->nodes + ni : NULL;
|
||||
// return &pbvh->nodes[pbvh_bmesh_node_index_from_vert(pbvh, key)];
|
||||
}
|
||||
|
||||
BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *pbvh, const BMFace *key)
|
||||
{
|
||||
int ni = pbvh_bmesh_node_index_from_face(pbvh, key);
|
||||
|
||||
return ni >= 0 ? pbvh->nodes + ni : NULL;
|
||||
// return &pbvh->nodes[pbvh_bmesh_node_index_from_face(pbvh, key)];
|
||||
}
|
||||
bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index);
|
||||
void pbvh_bmesh_check_nodes(PBVH *pbvh);
|
||||
void bke_pbvh_insert_face_finalize(PBVH *pbvh, BMFace *f, const int ni);
|
||||
void bke_pbvh_insert_face(PBVH *pbvh, struct BMFace *f);
|
||||
void bke_pbvh_update_vert_boundary(int cd_dyn_vert,
|
||||
int cd_faceset_offset,
|
||||
BMVert *v,
|
||||
int bound_symmetry);
|
||||
|
||||
BLI_INLINE bool pbvh_check_vert_boundary(PBVH *pbvh, struct BMVert *v)
|
||||
{
|
||||
MDynTopoVert *mv = (MDynTopoVert *)BM_ELEM_CD_GET_VOID_P(v, pbvh->cd_dyn_vert);
|
||||
|
||||
if (mv->flag & DYNVERT_NEED_BOUNDARY) {
|
||||
bke_pbvh_update_vert_boundary(
|
||||
pbvh->cd_dyn_vert, pbvh->cd_faceset_offset, v, pbvh->boundary_symmetry);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void pbvh_bmesh_check_other_verts(PBVHNode *node);
|
||||
|
||||
//#define DEFRAGMENT_MEMORY
|
||||
|
@@ -69,6 +69,7 @@
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_brush_engine.h"
|
||||
#include "BKE_cachefile.h"
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_colortools.h"
|
||||
@@ -849,6 +850,11 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
|
||||
}
|
||||
if (tos->sculpt) {
|
||||
BLO_write_struct(writer, Sculpt, tos->sculpt);
|
||||
|
||||
if (tos->sculpt->channels) {
|
||||
BKE_brush_channelset_write(writer, tos->sculpt->channels);
|
||||
}
|
||||
|
||||
BKE_paint_blend_write(writer, &tos->sculpt->paint);
|
||||
}
|
||||
if (tos->uvsculpt) {
|
||||
@@ -1050,6 +1056,18 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
sce->toolsettings->particle.object = NULL;
|
||||
sce->toolsettings->gp_sculpt.paintcursor = NULL;
|
||||
|
||||
if (sce->toolsettings->sculpt && sce->toolsettings->sculpt->channels) {
|
||||
BLO_read_data_address(reader, &sce->toolsettings->sculpt->channels);
|
||||
BKE_brush_channelset_read(reader, sce->toolsettings->sculpt->channels);
|
||||
}
|
||||
else if (sce->toolsettings->sculpt) {
|
||||
sce->toolsettings->sculpt->channels = BKE_brush_channelset_create();
|
||||
}
|
||||
|
||||
if (sce->toolsettings->sculpt) {
|
||||
BKE_brush_check_toolsettings(sce->toolsettings->sculpt);
|
||||
}
|
||||
|
||||
/* relink grease pencil interpolation curves */
|
||||
BLO_read_data_address(reader, &sce->toolsettings->gp_interpolate.custom_ipo);
|
||||
if (sce->toolsettings->gp_interpolate.custom_ipo) {
|
||||
@@ -1597,6 +1615,14 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
|
||||
}
|
||||
if (ts->sculpt) {
|
||||
ts->sculpt = MEM_dupallocN(ts->sculpt);
|
||||
|
||||
if (ts->sculpt->channels) {
|
||||
ts->sculpt->channels = BKE_brush_channelset_copy(ts->sculpt->channels);
|
||||
}
|
||||
else {
|
||||
ts->sculpt->channels = BKE_brush_channelset_create();
|
||||
}
|
||||
|
||||
BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag);
|
||||
}
|
||||
if (ts->uvsculpt) {
|
||||
@@ -1652,6 +1678,11 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
|
||||
}
|
||||
if (toolsettings->sculpt) {
|
||||
BKE_paint_free(&toolsettings->sculpt->paint);
|
||||
|
||||
if (toolsettings->sculpt->channels) {
|
||||
BKE_brush_channelset_free(toolsettings->sculpt->channels);
|
||||
}
|
||||
|
||||
MEM_freeN(toolsettings->sculpt);
|
||||
}
|
||||
if (toolsettings->uvsculpt) {
|
||||
@@ -2393,6 +2424,7 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_
|
||||
if (check_rendered_viewport_visible(bmain)) {
|
||||
BMesh *bm = mesh->edit_mesh->bm;
|
||||
BM_mesh_bm_to_me(bmain,
|
||||
NULL,
|
||||
bm,
|
||||
mesh,
|
||||
(&(struct BMeshToMeshParams){
|
||||
|
@@ -360,6 +360,7 @@ static void eval_displacement(SubdivDisplacement *displacement,
|
||||
BKE_multires_construct_tangent_matrix(tangent_matrix, dPdu, dPdv, corner_of_quad);
|
||||
mul_v3_m3v3(r_D, tangent_matrix, tangent_D);
|
||||
/* For the boundary points of grid average two (or all) neighbor grids. */
|
||||
|
||||
const int corner = displacement_get_face_corner(data, ptex_face_index, u, v);
|
||||
average_displacement(displacement, average_with, ptex_face_index, corner, grid_u, grid_v, r_D);
|
||||
}
|
||||
|
@@ -1866,11 +1866,14 @@ static const MeshElemMap *ccgDM_getPolyMap(Object *ob, DerivedMesh *dm)
|
||||
|
||||
BKE_mesh_vert_poly_map_create(&ccgdm->pmap,
|
||||
&ccgdm->pmap_mem,
|
||||
me->mvert,
|
||||
me->medge,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->totvert,
|
||||
me->totpoly,
|
||||
me->totloop);
|
||||
me->totloop,
|
||||
false);
|
||||
}
|
||||
|
||||
return ccgdm->pmap;
|
||||
|
@@ -21,7 +21,7 @@
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)) && !defined(_MSC_VER)
|
||||
#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
|
||||
# include "sanitizer/asan_interface.h"
|
||||
#else
|
||||
/* Ensure return value is used. Just using UNUSED_VARS results in a warning. */
|
||||
@@ -40,3 +40,59 @@
|
||||
* Mark a region of memory as usable again.
|
||||
*/
|
||||
#define BLI_asan_unpoison(addr, size) ASAN_UNPOISON_MEMORY_REGION(addr, size)
|
||||
|
||||
#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
|
||||
# include "MEM_guardedalloc.h"
|
||||
|
||||
static void *BLI_asan_safe_malloc(size_t size, const char *tag)
|
||||
{
|
||||
// align size at 16 bytes
|
||||
size += 15 - (size & 15);
|
||||
|
||||
// add safe padding
|
||||
size += 32;
|
||||
|
||||
void *ret = MEM_mallocN(size, tag);
|
||||
|
||||
int *iptr = (int *)ret;
|
||||
*iptr = (int)size;
|
||||
|
||||
char *ptr = (char *)ret;
|
||||
|
||||
ptr[4] = 't';
|
||||
ptr[5] = 'a';
|
||||
ptr[6] = 'g';
|
||||
ptr[7] = '1';
|
||||
|
||||
BLI_asan_poison(ptr, 16);
|
||||
BLI_asan_poison(ptr + size - 16, 16);
|
||||
|
||||
ret = (void *)(ptr + 16);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void BLI_asan_safe_free(void *mem)
|
||||
{
|
||||
if (!mem) {
|
||||
return;
|
||||
}
|
||||
|
||||
mem = (void *)(((char *)mem) - 16);
|
||||
|
||||
BLI_asan_unpoison(mem, 16);
|
||||
int *iptr = (int *)mem;
|
||||
volatile char *ptr = (char *)mem;
|
||||
|
||||
if (ptr[4] != 't' || ptr[5] != 'a' || ptr[6] != 'g' || ptr[7] != '1') {
|
||||
BLI_asan_poison(mem, 16);
|
||||
*ptr = 1; // deliberately trigger asan fault
|
||||
}
|
||||
|
||||
BLI_asan_unpoison(ptr + iptr[0] - 16, 16);
|
||||
MEM_freeN((void *)ptr);
|
||||
}
|
||||
#else
|
||||
# define BLI_asan_safe_malloc(size, tag) MEM_mallocN(size, tag)
|
||||
# define BLI_asan_safe_free(mem) MEM_SAFE_FREE(mem)
|
||||
#endif
|
||||
|
@@ -33,6 +33,12 @@
|
||||
/* hint to mark function arguments expected to be non-null
|
||||
* if no arguments are given to the macro, all of pointer
|
||||
* arguments would be expected to be non-null
|
||||
*
|
||||
* ONE-INDEXED!
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* void func(void *a, void *b, void *b) ATTR_NONNULL(1, 2, 3)
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
# define ATTR_NONNULL(args...) __attribute__((nonnull(args)))
|
||||
@@ -99,6 +105,17 @@
|
||||
# define ATTR_ALIGN(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
|
||||
/* Disable optimization for a function (for debugging use only!)*/
|
||||
#ifdef __clang__
|
||||
# define ATTR_NO_OPT __attribute__((optnone))
|
||||
#elif defined(_MSC_VER)
|
||||
# define ATTR_NO_OPT __pragma(optimize("", off))
|
||||
#elif defined(__GNUC__)
|
||||
# define ATTR_NO_OPT __attribute__((optimize("O0")))
|
||||
#else
|
||||
# define ATTR_NO_OPT
|
||||
#endif
|
||||
|
||||
/* Alignment directive */
|
||||
#ifdef _WIN64
|
||||
# define ALIGN_STRUCT __declspec(align(64))
|
||||
|
@@ -101,6 +101,22 @@ void *BLI_ghash_lookup_default(const GHash *gh,
|
||||
const void *key,
|
||||
void *val_default) ATTR_WARN_UNUSED_RESULT;
|
||||
void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
|
||||
/**
|
||||
* Lookup a pointer to the value of \a key in \a gh.
|
||||
*
|
||||
* \param key: The key to lookup.
|
||||
* \param r_key: Pointer to variable to store the key as stored in the ghash
|
||||
* \param r_val: Similar to BLI_ghash_ensure_p, pointer to the ghash pointer
|
||||
* that stores the value
|
||||
*
|
||||
* \returns true if the value was found
|
||||
*
|
||||
* \note This has 2 main benefits over #BLI_ghash_lookup.
|
||||
* - The value can be modified in-place without further function calls (faster).
|
||||
* - The key as stored in the ghash is returned in r_key
|
||||
*/
|
||||
bool BLI_ghash_lookup_p_ex(GHash *gh, const void *key, void **r_key, void ***r_val);
|
||||
|
||||
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT;
|
||||
bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_key, void ***r_val)
|
||||
ATTR_WARN_UNUSED_RESULT;
|
||||
@@ -188,6 +204,53 @@ BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi)
|
||||
|
||||
typedef struct GSet GSet;
|
||||
|
||||
struct SmallHash;
|
||||
|
||||
#include "BLI_smallhash.h"
|
||||
|
||||
typedef struct TableGSet {
|
||||
struct SmallHash ptr_to_idx;
|
||||
void **elems;
|
||||
int size, length;
|
||||
int cur;
|
||||
} TableGSet;
|
||||
|
||||
TableGSet *BLI_table_gset_new(const char *info);
|
||||
TableGSet *BLI_table_gset_new_ex(const char *info, int size);
|
||||
void BLI_table_gset_free(TableGSet *ts, GHashKeyFreeFP freefp);
|
||||
void BLI_table_gset_insert(TableGSet *ts, void *elem);
|
||||
bool BLI_table_gset_add(TableGSet *ts, void *elem);
|
||||
void BLI_table_gset_remove(TableGSet *ts, void *elem, GHashKeyFreeFP freefp);
|
||||
bool BLI_table_gset_haskey(TableGSet *ts, void *elem);
|
||||
|
||||
int BLI_table_gset_len(TableGSet *ts);
|
||||
|
||||
#define TGSET_ITER(v, ts) \
|
||||
{ \
|
||||
int _i1; \
|
||||
for (_i1 = 0; _i1 < (ts)->cur; _i1++) { \
|
||||
if (!(ts)->elems[_i1]) \
|
||||
continue; \
|
||||
v = (ts)->elems[_i1];
|
||||
|
||||
#define TGSET_ITER_END \
|
||||
} \
|
||||
}
|
||||
|
||||
#define TGSET_ITER_INDEX(v, ts, index) \
|
||||
{ \
|
||||
int _i1; \
|
||||
index = -1; \
|
||||
for (_i1 = 0; _i1 < (ts)->cur; _i1++) { \
|
||||
if (!(ts)->elems[_i1]) \
|
||||
continue; \
|
||||
v = (ts)->elems[_i1]; \
|
||||
index++;
|
||||
|
||||
#define TGSET_ITER_INDEX_END \
|
||||
} \
|
||||
}
|
||||
|
||||
typedef GHashHashFP GSetHashFP;
|
||||
typedef GHashCmpFP GSetCmpFP;
|
||||
typedef GHashKeyFreeFP GSetKeyFreeFP;
|
||||
|
@@ -52,7 +52,7 @@
|
||||
#define BLI_LINKSTACK_SIZE(var) BLI_mempool_len(var##_pool_)
|
||||
|
||||
/* check for typeof() */
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define BLI_LINKSTACK_PUSH(var, ptr) \
|
||||
(CHECK_TYPE_INLINE(ptr, typeof(var##_type_)), \
|
||||
BLI_linklist_prepend_pool(&(var), ptr, var##_pool_))
|
||||
|
@@ -87,11 +87,35 @@ enum {
|
||||
* order of allocation when no chunks have been freed.
|
||||
*/
|
||||
BLI_MEMPOOL_ALLOW_ITER = (1 << 0),
|
||||
|
||||
/* allow random access, implies BLI_MEMPOOL_ALLOW_ITER since we
|
||||
need the freewords to detect free state of elements*/
|
||||
BLI_MEMPOOL_RANDOM_ACCESS = (1 << 1) | (1 << 0)
|
||||
};
|
||||
|
||||
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL();
|
||||
void *BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
|
||||
|
||||
/*
|
||||
This preallocates a mempool suitable for threading. totelem elements are preallocated
|
||||
in chunks of size pchunk, and returned in r_chunks.
|
||||
*/
|
||||
|
||||
BLI_mempool *BLI_mempool_create_for_tasks(const unsigned int esize,
|
||||
int totelem,
|
||||
const int pchunk,
|
||||
void ***r_chunks,
|
||||
int *r_totchunk,
|
||||
int *r_esize,
|
||||
int flag);
|
||||
|
||||
// memory coherence stuff
|
||||
int BLI_mempool_find_elems_fuzzy(
|
||||
BLI_mempool *pool, int idx, int range, void **r_elems, int r_elems_size);
|
||||
|
||||
int BLI_mempool_get_size(BLI_mempool *pool);
|
||||
int BLI_mempool_find_real_index(BLI_mempool *pool, void *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -39,11 +39,13 @@ typedef struct {
|
||||
#define SMSTACKSIZE 131
|
||||
typedef struct SmallHash {
|
||||
unsigned int nbuckets;
|
||||
unsigned int nentries;
|
||||
unsigned int nentries, nfreecells;
|
||||
unsigned int cursize;
|
||||
|
||||
SmallHashEntry *buckets;
|
||||
SmallHashEntry buckets_stack[SMSTACKSIZE];
|
||||
|
||||
bool using_stack;
|
||||
} SmallHash;
|
||||
|
||||
typedef struct {
|
||||
@@ -57,22 +59,25 @@ void BLI_smallhash_release(SmallHash *sh) ATTR_NONNULL(1);
|
||||
void BLI_smallhash_insert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
|
||||
bool BLI_smallhash_reinsert(SmallHash *sh, uintptr_t key, void *item) ATTR_NONNULL(1);
|
||||
bool BLI_smallhash_remove(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
|
||||
void *BLI_smallhash_lookup(const SmallHash *sh, uintptr_t key)
|
||||
void *BLI_smallhash_lookup(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
void **BLI_smallhash_lookup_p(SmallHash *sh, uintptr_t key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
void **BLI_smallhash_lookup_p(const SmallHash *sh, uintptr_t key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
bool BLI_smallhash_haskey(const SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
|
||||
int BLI_smallhash_len(const SmallHash *sh) ATTR_NONNULL(1);
|
||||
bool BLI_smallhash_haskey(SmallHash *sh, uintptr_t key) ATTR_NONNULL(1);
|
||||
int BLI_smallhash_len(SmallHash *sh) ATTR_NONNULL(1);
|
||||
void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
void **BLI_smallhash_iternext_p(SmallHashIter *iter, uintptr_t *key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
void *BLI_smallhash_iternew(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
|
||||
void *BLI_smallhash_iternew(SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
|
||||
void **BLI_smallhash_iternew_p(SmallHash *sh, SmallHashIter *iter, uintptr_t *key)
|
||||
ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
/* void BLI_smallhash_print(SmallHash *sh); */ /* UNUSED */
|
||||
|
||||
void BLI_smallhash_clear(SmallHash *sh, uintptr_t key);
|
||||
bool BLI_smallhash_ensure_p(SmallHash *sh, uintptr_t key, void ***item);
|
||||
bool BLI_smallhash_remove_p(SmallHash *sh, uintptr_t key, void **val);
|
||||
|
||||
#ifdef DEBUG
|
||||
double BLI_smallhash_calc_quality(SmallHash *sh);
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user