Compare commits
540 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43aa145c94 | ||
|
|
1608ed43c1 | ||
|
|
fa103a69f9 | ||
|
|
f8520f9dd3 | ||
|
|
3a372afc0e | ||
|
|
95d6bec68f | ||
|
|
56f2e20cb4 | ||
|
|
4cbcaba7f2 | ||
|
|
aeeca6e2c0 | ||
|
|
74704d0d2a | ||
|
|
0b384bdd72 | ||
|
|
e9cf3a6806 | ||
|
|
c5f9068664 | ||
|
|
992bbbba1c | ||
|
|
fe9dd63558 | ||
|
|
8e45003c27 | ||
|
|
f53d824e07 | ||
|
|
259670af85 | ||
|
|
c7e9430f99 | ||
|
|
afe573d2eb | ||
|
|
547d9817db | ||
|
|
9c63243fe7 | ||
|
|
5535ba6b47 | ||
|
|
52a80f98ed | ||
|
|
9600319094 | ||
|
|
9b930c8716 | ||
|
|
eb0d2e5b2c | ||
|
|
5e2722475a | ||
|
|
b1e406731d | ||
|
|
8c6d51cb71 | ||
|
|
4b205084f8 | ||
|
|
eb910b0bae | ||
|
|
09a6a1f259 | ||
|
|
315618a18b | ||
|
|
59af03695b | ||
|
|
e1851f7b5b | ||
|
|
a126b4003f | ||
|
|
9067de26ac | ||
|
|
260c5345fd | ||
|
|
e3dd05ef21 | ||
|
|
9379bcedf9 | ||
|
|
2c91210d6e | ||
|
|
f721d935e4 | ||
|
|
66597cade3 | ||
|
|
3c5f39e26a | ||
|
|
24e3176f1b | ||
|
|
e59757e3e8 | ||
|
|
282de8c7f5 | ||
|
|
541021f29c | ||
|
|
e01b9dcd39 | ||
|
|
8d4567b930 | ||
|
|
6f6988a487 | ||
|
|
435ab2ce77 | ||
|
|
1afd723c4e | ||
|
|
b09f7f5ac7 | ||
|
|
1b3f0f9ec0 | ||
|
|
d1d68721ac | ||
|
|
2f4afe5b68 | ||
|
|
47fcc70756 | ||
|
|
0e86b696c5 | ||
|
|
54f05b409c | ||
|
|
350dff9b98 | ||
|
|
f198221812 | ||
|
|
dee08b4216 | ||
|
|
e02d074a85 | ||
|
|
8e2da87b97 | ||
|
|
2deba06212 | ||
|
|
a6ac8e1f71 | ||
|
|
69436a9032 | ||
|
|
50d91d13be | ||
|
|
54a6db146e | ||
|
|
3b31fe91a6 | ||
|
|
90c5219be9 | ||
|
|
669fe29173 | ||
|
|
d7d06c8234 | ||
|
|
4754c1322d | ||
|
|
acb093c277 | ||
|
|
21d54edeb9 | ||
|
|
20ea0968da | ||
|
|
398d8c52a2 | ||
|
|
f82d12d381 | ||
|
|
91ee5724ca | ||
|
|
a82443f271 | ||
|
|
1cd0b70055 | ||
|
|
8f8904ad0f | ||
|
|
e975e389df | ||
|
|
d3242393e0 | ||
|
|
ce7d0e81bd | ||
|
|
0cf16e6f8f | ||
|
|
0ab395794e | ||
|
|
ac06a8394b | ||
|
|
46dd1ad154 | ||
|
|
e57a7b6f3b | ||
|
|
409128b07f | ||
|
|
fd562061ee | ||
|
|
c6a7dc8f9c | ||
|
|
5275f7e852 | ||
|
|
6ec19e4630 | ||
|
|
690ac8d4b1 | ||
|
|
7ae1cd33be | ||
|
|
a7c6c184da | ||
|
|
29d6b423a3 | ||
|
|
b3590c5ae6 | ||
|
|
67f549d86d | ||
|
|
9096265bff | ||
|
|
ce265b3948 | ||
|
|
7fee70543d | ||
|
|
f3a48bb0f0 | ||
|
|
c151c12b95 | ||
|
|
b8d999066d | ||
|
|
0e816492b4 | ||
|
|
c6ef099e18 | ||
|
|
1c5872da0c | ||
|
|
d95e94fa07 | ||
|
|
d7bbbd9d40 | ||
|
|
cf56659b18 | ||
|
|
4163b8e40b | ||
|
|
4ca6a5c52c | ||
|
|
511811de3b | ||
|
|
6ef4dfb61f | ||
|
|
5ca2a3b0f7 | ||
|
|
88794d0288 | ||
|
|
30e76a7c11 | ||
|
|
41eb687243 | ||
|
|
5191baa659 | ||
|
|
8159eff664 | ||
|
|
c6eb3d790e | ||
|
|
f62fc8ab15 | ||
|
|
75e85701c6 | ||
|
|
cd85afc9a5 | ||
|
|
b9ba472eda | ||
|
|
bf9d3acf33 | ||
|
|
bd7e291787 | ||
|
|
73b34b6d89 | ||
|
|
f2c7290ee8 | ||
|
|
6f6938f5bb | ||
|
|
601ff92871 | ||
|
|
f119986fad | ||
|
|
402cd21f87 | ||
|
|
8cb694af89 | ||
|
|
73d8cedf7e | ||
|
|
b7e8d36cf8 | ||
|
|
45f5eb9671 | ||
|
|
16fe6d0dcf | ||
|
|
b633c3ffea | ||
|
|
ca1696823c | ||
|
|
c1cc9d484a | ||
|
|
db75cb3e17 | ||
|
|
b8a17c8f22 | ||
|
|
74dff061ff | ||
|
|
3dd846b600 | ||
|
|
8a2e24ecd0 | ||
|
|
6ccca51fee | ||
|
|
a4b3c3d1ad | ||
|
|
bc8947289b | ||
|
|
e7c506c6ec | ||
|
|
8236964029 | ||
|
|
aadecaf102 | ||
|
|
b55e45eef6 | ||
|
|
adbc928148 | ||
|
|
c4c206076a | ||
|
|
5c077d7037 | ||
|
|
8583a2f4f7 | ||
|
|
ed8416ea10 | ||
|
|
deb7454cf7 | ||
|
|
8c40af5aee | ||
|
|
dd893bab41 | ||
|
|
759ee62e7c | ||
|
|
1e9b79e2c1 | ||
|
|
315883a28c | ||
|
|
19b85afe12 | ||
|
|
b2e8a31d68 | ||
|
|
b4b12732cb | ||
|
|
c714c57bb2 | ||
|
|
4697216c5e | ||
|
|
e2fa94e2c3 | ||
|
|
7578a27bf7 | ||
|
|
14e0b3c9e6 | ||
|
|
815acfc7da | ||
|
|
7d8af7d413 | ||
|
|
39810ed516 | ||
|
|
9cbcf8fe34 | ||
|
|
02b476035b | ||
|
|
9eb338f417 | ||
|
|
15e30604fc | ||
|
|
21f677cf58 | ||
|
|
3ead892b1c | ||
|
|
a59e87a896 | ||
|
|
96df7b82de | ||
|
|
5cb5d284c3 | ||
|
|
869517b9c6 | ||
|
|
56cefce1cc | ||
|
|
165af85894 | ||
|
|
7c073c1db7 | ||
|
|
061178ad82 | ||
|
|
dbc7c6e74d | ||
|
|
d87a48ea06 | ||
|
|
b36bb8b5bb | ||
|
|
2ed16c9736 | ||
|
|
c031649979 | ||
|
|
e0746fca12 | ||
|
|
2075042ba7 | ||
|
|
499cd48763 | ||
|
|
5d826b2b62 | ||
|
|
b20943d497 | ||
|
|
b4ab9a4e57 | ||
|
|
cd36a1fe16 | ||
|
|
1cda80cbe7 | ||
|
|
ffd0e6b79d | ||
|
|
a7728b87fc | ||
|
|
c218789abc | ||
|
|
3656cb9fdb | ||
|
|
e93fdf4615 | ||
|
|
6722e25cbe | ||
|
|
790db4283c | ||
|
|
a0359473ff | ||
|
|
ccfdcce5c1 | ||
|
|
811849fa23 | ||
|
|
1051fd9d42 | ||
|
|
5490a992ca | ||
|
|
2d29fb8d15 | ||
|
|
589035c1db | ||
|
|
8f6a578ec0 | ||
|
|
a2fcf4edac | ||
|
|
f56ac5210c | ||
|
|
576069a84d | ||
|
|
7ea7d4cf6c | ||
|
|
21e1359b37 | ||
|
|
eebee9b7c1 | ||
|
|
bfc986a97d | ||
|
|
d65a52242e | ||
|
|
c82c791061 | ||
|
|
bcd18a01d8 | ||
|
|
53a4931974 | ||
|
|
1f7751618e | ||
|
|
497babe8e9 | ||
|
|
973a90a34d | ||
|
|
3cff5cd1a8 | ||
|
|
8766335708 | ||
|
|
908fc939b1 | ||
|
|
73c4557a45 | ||
|
|
accfcbbf5c | ||
|
|
5a36450e01 | ||
|
|
839f4eab7e | ||
|
|
fec0559d11 | ||
|
|
e46fc0a805 | ||
|
|
fb7751360c | ||
|
|
0c2e7d7028 | ||
|
|
fe2e68b410 | ||
|
|
166c4df0b3 | ||
|
|
68684855c6 | ||
|
|
fa0de18ffe | ||
|
|
24ca32f9f7 | ||
|
|
f63de0d0cc | ||
|
|
f6db6058e1 | ||
|
|
d23632ef46 | ||
|
|
1048f213c7 | ||
|
|
98d88bff94 | ||
|
|
861fccd2d6 | ||
|
|
715c3b8510 | ||
|
|
3c6c7c4138 | ||
|
|
95106ca1c2 | ||
|
|
ac106b0aff | ||
|
|
001e45627b | ||
|
|
b8c3457644 | ||
|
|
5f6dcfa82a | ||
|
|
f2dd944acd | ||
|
|
d0f69ebb75 | ||
|
|
04737fb0e8 | ||
|
|
d78550e83e | ||
|
|
c640585bc3 | ||
|
|
a926cdc5be | ||
|
|
43e66b57a0 | ||
|
|
ee60a9801b | ||
|
|
fb69220b95 | ||
|
|
1cf7f67af5 | ||
|
|
8497ba1898 | ||
|
|
234259da91 | ||
|
|
ef7f309012 | ||
|
|
d372fa1a0f | ||
|
|
ea9005868b | ||
|
|
0a3a4a51bd | ||
|
|
1dbd913d9d | ||
|
|
22cded7ccc | ||
|
|
4851f1ad48 | ||
|
|
0d94dd7bf8 | ||
|
|
bbe7f6adfb | ||
|
|
828941a204 | ||
|
|
2ce3f2c131 | ||
|
|
8943552c1c | ||
|
|
dadbb00b85 | ||
|
|
852a8407c8 | ||
|
|
bfbbcad8e5 | ||
|
|
c684987908 | ||
|
|
53b8f70de8 | ||
|
|
a1eb30ae87 | ||
|
|
c4cb9de44b | ||
|
|
0a89503edd | ||
|
|
f12bd741e2 | ||
|
|
e35039faf7 | ||
|
|
a756943628 | ||
|
|
a9c3e13e5e | ||
|
|
67c8ac2b04 | ||
|
|
82044399e4 | ||
|
|
fdcf2eda5a | ||
|
|
e0997f1f04 | ||
|
|
58859ee709 | ||
|
|
c3771e2fd5 | ||
|
|
2e49365b0f | ||
|
|
cd87aadab3 | ||
|
|
e58f8856f4 | ||
|
|
18a48e6609 | ||
|
|
929b75989c | ||
|
|
7d98030edc | ||
|
|
846d573dd0 | ||
|
|
5805fe636a | ||
|
|
3db9c6a9ff | ||
|
|
22bcf83cb9 | ||
|
|
117eca3c98 | ||
|
|
81affe719f | ||
|
|
3febec4aa4 | ||
|
|
a78c6072ce | ||
|
|
aa6a57be63 | ||
|
|
fd29dd9508 | ||
|
|
5080ebf88f | ||
|
|
873df7805b | ||
|
|
009fb10927 | ||
|
|
3898d29741 | ||
|
|
1c521a3743 | ||
|
|
098d1b30ff | ||
|
|
484108dafc | ||
|
|
029d260ad8 | ||
|
|
e6bc8f8583 | ||
|
|
77a13963bb | ||
|
|
656eacbb09 | ||
|
|
98f9a09b39 | ||
|
|
7e8e8bdb26 | ||
|
|
e2a0f801b9 | ||
|
|
75b31b4151 | ||
|
|
f0763fd31c | ||
|
|
162e7b7699 | ||
|
|
7158a3c83d | ||
|
|
1fa30dd337 | ||
|
|
250049537f | ||
|
|
76e5311320 | ||
|
|
11098cd6d4 | ||
|
|
78a0b347fc | ||
|
|
08a23de051 | ||
|
|
a02ad53c73 | ||
|
|
9400701c96 | ||
|
|
aa983108e8 | ||
|
|
7dca333166 | ||
|
|
0f1ecf66ab | ||
|
|
74984b5a3c | ||
|
|
c5d5984885 | ||
|
|
c1ccfcb988 | ||
|
|
51dc0550d5 | ||
|
|
ac9e36549b | ||
|
|
009e9a598a | ||
|
|
1502ef2661 | ||
|
|
40f9e12bdf | ||
|
|
2fc783e67e | ||
|
|
4f8e6a188a | ||
|
|
b0e44ad1bd | ||
|
|
4a630b1780 | ||
|
|
ffa5e6099d | ||
|
|
8d1cd7008f | ||
|
|
31b5c5e9dd | ||
|
|
0e21a16c1c | ||
|
|
f666384a1d | ||
|
|
afacfcee94 | ||
|
|
7262bf96b8 | ||
|
|
3db489f4df | ||
|
|
6526c28e47 | ||
|
|
e473b9bf10 | ||
|
|
0bde458c27 | ||
|
|
66739ac820 | ||
|
|
4a3763d8d1 | ||
|
|
4230127459 | ||
|
|
a4c672252d | ||
|
|
d5d0473487 | ||
|
|
9bbad1f8f0 | ||
|
|
0523965822 | ||
|
|
cb8cd702e1 | ||
|
|
86b5737d51 | ||
|
|
4027ec7a67 | ||
|
|
c2748a2246 | ||
|
|
5c06afc977 | ||
|
|
4c82a5660f | ||
|
|
beacb5c701 | ||
|
|
8355331cbe | ||
|
|
dc9cb07a81 | ||
|
|
57fe7d9ad0 | ||
|
|
00336de59a | ||
|
|
b37b48f039 | ||
|
|
42ca1a8994 | ||
|
|
db678238ef | ||
|
|
861f88dd30 | ||
|
|
77d42f1eb9 | ||
|
|
364a13017c | ||
|
|
8183deeb30 | ||
|
|
bb56d0a752 | ||
|
|
41eafa4ede | ||
|
|
ce7629200f | ||
|
|
5dca06d3d4 | ||
|
|
b1d18c7f29 | ||
|
|
0b2d019e61 | ||
|
|
ab0dde7fe8 | ||
|
|
ef01d2af82 | ||
|
|
08084799b9 | ||
|
|
3642e401da | ||
|
|
094d284e62 | ||
|
|
2c7459e08d | ||
|
|
315d2c4daf | ||
|
|
e61cabf1ce | ||
|
|
994f409291 | ||
|
|
7d124012c2 | ||
|
|
4d3c80e273 | ||
|
|
a332a7fc35 | ||
|
|
2fb945a489 | ||
|
|
4d2517d163 | ||
|
|
b4848f308f | ||
|
|
1c8876cead | ||
|
|
1bcb6ad20d | ||
|
|
66aaa9cf80 | ||
|
|
61d365e957 | ||
|
|
006b319c3a | ||
|
|
e38ec797fd | ||
|
|
94b42e7a9b | ||
|
|
61097dac72 | ||
|
|
116fe01dee | ||
|
|
ba2bf9f366 | ||
|
|
a5b68f2da2 | ||
|
|
97edb0f954 | ||
|
|
a3531b931b | ||
|
|
0438f070f7 | ||
|
|
f53e36c430 | ||
|
|
8889e2de64 | ||
|
|
2d0b310e19 | ||
|
|
dfb465a11b | ||
|
|
9ed2dc755c | ||
|
|
e70342b356 | ||
|
|
ba0fd794d7 | ||
|
|
dbd7de628f | ||
|
|
d6fdaa93a4 | ||
|
|
80076833d1 | ||
|
|
dc9d3fbf96 | ||
|
|
e12548ab8c | ||
|
|
894261862d | ||
|
|
07a261a259 | ||
|
|
34a7bf4dbb | ||
|
|
5988f6cf88 | ||
|
|
039be1f8e9 | ||
|
|
70e92a1cea | ||
|
|
2af2e37dcd | ||
|
|
a6559b1e51 | ||
|
|
361b8852df | ||
|
|
ff201ce3f9 | ||
|
|
de2ce83a8d | ||
|
|
f37d83abe1 | ||
|
|
ee610ceb3f | ||
|
|
5affacab70 | ||
|
|
924011f36e | ||
|
|
70b5a6f05b | ||
|
|
05c7270dcf | ||
|
|
a75e34d1c2 | ||
|
|
f7139ac20e | ||
|
|
e43d718e0f | ||
|
|
cc0b5e660d | ||
|
|
8f525a37da | ||
|
|
5e62d2b104 | ||
|
|
6c373ee31e | ||
|
|
d98c46beb0 | ||
|
|
850772a4ce | ||
|
|
08be65e649 | ||
|
|
ed8e37ed89 | ||
|
|
1732d6d427 | ||
|
|
bb9a958a1e | ||
|
|
f1b8c36a28 | ||
|
|
03ed12a9b1 | ||
|
|
30f5a3a162 | ||
|
|
e4a3f76f55 | ||
|
|
f5bdb56a7c | ||
|
|
64d4a9e240 | ||
|
|
71d9084a95 | ||
|
|
9d6092faaa | ||
|
|
bb0f17ae6f | ||
|
|
ebb46999d8 | ||
|
|
1c48aa8f97 | ||
|
|
bdc0ad2b8f | ||
|
|
ac8d5e5ab3 | ||
|
|
41416dcffe | ||
|
|
dda7cb5791 | ||
|
|
f7fdeeea9b | ||
|
|
9d7d7590a7 | ||
|
|
77848afc94 | ||
|
|
8f7e96e2a5 | ||
|
|
eab807daeb | ||
|
|
c4bfdcbeac | ||
|
|
3801949887 | ||
|
|
29d5c951c5 | ||
|
|
eb4b0d630f | ||
|
|
b6225d1d9a | ||
|
|
32ec2be0b6 | ||
|
|
d7dfa91f6f | ||
|
|
c4cc9dd417 | ||
|
|
884b707385 | ||
|
|
acbc81c1ea | ||
|
|
cc60dcc8a4 | ||
|
|
275f85e7a6 | ||
|
|
24f99a2920 | ||
|
|
2acfbf12ed | ||
|
|
b0972de510 | ||
|
|
af58636c7c | ||
|
|
7341ad5e6e | ||
|
|
744e6c63b6 | ||
|
|
31aa30e3d0 | ||
|
|
ebb4489c01 | ||
|
|
31b3ae584e | ||
|
|
151afe4663 | ||
|
|
b03f7c1504 | ||
|
|
bceaee6e41 | ||
|
|
0c33c0de2e | ||
|
|
1b32c79a5e | ||
|
|
dd35f1bd68 | ||
|
|
9c0d8bbeb1 | ||
|
|
02753bfc7d | ||
|
|
88ae36f4e1 | ||
|
|
4dcf8f3f45 | ||
|
|
9e82297303 | ||
|
|
14a885f8d0 | ||
|
|
94aee52c64 | ||
|
|
755d3be89b | ||
|
|
6a3ee5fac4 | ||
|
|
6547452136 | ||
|
|
42bf70849c | ||
|
|
236fa2a284 | ||
|
|
2450b435a7 | ||
|
|
353e2977d6 | ||
|
|
641067c399 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -29,3 +29,9 @@ qtcreator-build/
|
||||
/indra/newview/res/viewerRes.rc
|
||||
/indra/newview/res/viewerRes_bc.rc
|
||||
/indra/newview/English.lproj/InfoPlist.strings
|
||||
/indra/newview/linux_tools/handle_secondlifeprotocol.sh
|
||||
/indra/newview/linux_tools/install.sh
|
||||
/indra/newview/linux_tools/refresh_desktop_app_entry.sh
|
||||
/indra/newview/linux_tools/wrapper.sh
|
||||
|
||||
|
||||
|
||||
29
LICENSES/LEGAL-intel_matrixlib.txt
Normal file
29
LICENSES/LEGAL-intel_matrixlib.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
INTEL LICENSE AGREEMENT
|
||||
|
||||
IMPORTANT - READ BEFORE COPYING OR USING.
|
||||
Do not use or load this library and any associated materials (collectively,
|
||||
the "Software") until you have read the following terms and conditions. By
|
||||
loading or using the Software, you agree to the terms of this Agreement. If
|
||||
you do not wish to so agree, do not use the Software.
|
||||
|
||||
LICENSE: Subject to the restrictions below, Intel Corporation ("Intel")
|
||||
grants to you the permission to use, copy, distribute and prepare derivative
|
||||
works of this Software for any purpose and without fee, provided, that
|
||||
Intel's copyright notice appear in all copies of the Software files.
|
||||
The distribution of derivative works of the Software is also subject to the
|
||||
following limitations: you (i) are solely responsible to your customers for
|
||||
any liability which may arise from the distribution, (ii) do not make any
|
||||
statement that your product is "certified", or that its performance is
|
||||
guaranteed, by Intel, and (iii) do not use Intel's name or trademarks to
|
||||
market your product without written permission.
|
||||
|
||||
EXCLUSION OF ALL WARRANTIES. The Software is provided "AS IS" without any
|
||||
express or implies warranty of any kind including warranties of
|
||||
merchantability, noninfringement, or fitness for a particular purpose.
|
||||
Intel does not warrant or assume responsibility for the accuracy or
|
||||
completeness of any information contained within the Software.
|
||||
As this Software is given free of charge, in no event shall Intel be liable
|
||||
for any damages whatsoever arising out of the use of or inability to use the
|
||||
Software, even if Intel has been adviced of the possibility of such damages.
|
||||
Intel does not assume any responsibility for any errors which may appear in
|
||||
this Software nor any responsibility to update it.
|
||||
@@ -293,7 +293,36 @@ void AIEngine::add(AIStateMachine* state_machine)
|
||||
}
|
||||
}
|
||||
|
||||
extern void print_statemachine_diagnostics(U64 total_clocks, U64 max_delta, AIEngine::queued_type::const_reference slowest_state_machine);
|
||||
#if STATE_MACHINE_PROFILING
|
||||
// Called from AIStateMachine::mainloop
|
||||
void print_statemachine_diagnostics(U64 total_clocks, AIStateMachine::StateTimerBase::TimeData& slowest_timer, AIEngine::queued_type::const_reference slowest_element)
|
||||
{
|
||||
AIStateMachine const& slowest_state_machine = slowest_element.statemachine();
|
||||
F64 const tfactor = 1000 / calc_clock_frequency();
|
||||
std::ostringstream msg;
|
||||
|
||||
U64 max_delta = slowest_timer.GetDuration();
|
||||
|
||||
if (total_clocks > max_delta)
|
||||
{
|
||||
msg << "AIStateMachine::mainloop did run for " << (total_clocks * tfactor) << " ms. The slowest ";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg << "AIStateMachine::mainloop: A ";
|
||||
}
|
||||
msg << "state machine " << "(" << slowest_state_machine.getName() << ") " << "ran for " << (max_delta * tfactor) << " ms";
|
||||
if (slowest_state_machine.getRuntime() > max_delta)
|
||||
{
|
||||
msg << " (" << (slowest_state_machine.getRuntime() * tfactor) << " ms in total now)";
|
||||
}
|
||||
msg << ".\n";
|
||||
|
||||
AIStateMachine::StateTimerBase::DumpTimers(msg);
|
||||
|
||||
llwarns << msg.str() << llendl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// MAIN-THREAD
|
||||
void AIEngine::mainloop(void)
|
||||
@@ -305,28 +334,33 @@ void AIEngine::mainloop(void)
|
||||
queued_element = engine_state_w->list.begin();
|
||||
}
|
||||
U64 total_clocks = 0;
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
U64 max_delta = 0;
|
||||
#if STATE_MACHINE_PROFILING
|
||||
queued_type::value_type slowest_element(NULL);
|
||||
AIStateMachine::StateTimerRoot::TimeData slowest_timer;
|
||||
#endif
|
||||
while (queued_element != end)
|
||||
{
|
||||
AIStateMachine& state_machine(queued_element->statemachine());
|
||||
U64 start = get_clock_count();
|
||||
if (!state_machine.sleep(start))
|
||||
AIStateMachine::StateTimerBase::TimeData time_data;
|
||||
if (!state_machine.sleep(get_clock_count()))
|
||||
{
|
||||
state_machine.multiplex(AIStateMachine::normal_run);
|
||||
AIStateMachine::StateTimerRoot timer(state_machine.getName());
|
||||
state_machine.multiplex(AIStateMachine::normal_run);
|
||||
time_data = timer.GetTimerData();
|
||||
}
|
||||
U64 delta = get_clock_count() - start;
|
||||
state_machine.add(delta);
|
||||
total_clocks += delta;
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
if (delta > max_delta)
|
||||
if (U64 delta = time_data.GetDuration())
|
||||
{
|
||||
max_delta = delta;
|
||||
slowest_element = *queued_element;
|
||||
}
|
||||
state_machine.add(delta);
|
||||
total_clocks += delta;
|
||||
#if STATE_MACHINE_PROFILING
|
||||
if (delta > slowest_timer.GetDuration())
|
||||
{
|
||||
slowest_element = *queued_element;
|
||||
slowest_timer = time_data;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool active = state_machine.active(this); // This locks mState shortly, so it must be called before locking mEngineState because add() locks mEngineState while holding mState.
|
||||
engine_state_type_wat engine_state_w(mEngineState);
|
||||
if (!active)
|
||||
@@ -340,8 +374,8 @@ void AIEngine::mainloop(void)
|
||||
}
|
||||
if (total_clocks >= sMaxCount)
|
||||
{
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
print_statemachine_diagnostics(total_clocks, max_delta, slowest_element);
|
||||
#if STATE_MACHINE_PROFILING
|
||||
print_statemachine_diagnostics(total_clocks, slowest_timer, slowest_element);
|
||||
#endif
|
||||
Dout(dc::statemachine, "Sorting " << engine_state_w->list.size() << " state machines.");
|
||||
engine_state_w->list.sort(QueueElementComp());
|
||||
@@ -373,7 +407,7 @@ void AIEngine::setMaxCount(F32 StateMachineMaxTime)
|
||||
sMaxCount = calc_clock_frequency() * StateMachineMaxTime / 1000;
|
||||
}
|
||||
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
#ifdef CWDEBUG
|
||||
char const* AIStateMachine::event_str(event_type event)
|
||||
{
|
||||
switch(event)
|
||||
@@ -752,6 +786,22 @@ void AIStateMachine::multiplex(event_type event)
|
||||
}
|
||||
}
|
||||
|
||||
#if STATE_MACHINE_PROFILING
|
||||
std::vector<AIStateMachine::StateTimerBase*> AIStateMachine::StateTimerBase::mTimerStack;
|
||||
AIStateMachine::StateTimerBase::TimeData AIStateMachine::StateTimerBase::TimeData::sRoot("");
|
||||
void AIStateMachine::StateTimer::TimeData::DumpTimer(std::ostringstream& msg, std::string prefix)
|
||||
{
|
||||
F64 const tfactor = 1000 / calc_clock_frequency();
|
||||
msg << prefix << mName << " " << (mEnd - mStart)*tfactor << "ms" << std::endl;
|
||||
prefix.push_back(' ');
|
||||
std::vector<TimeData>::iterator it;
|
||||
for (it = mChildren.begin(); it != mChildren.end(); ++it)
|
||||
{
|
||||
it->DumpTimer(msg, prefix);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
AIStateMachine::state_type AIStateMachine::begin_loop(base_state_type base_state)
|
||||
{
|
||||
DoutEntering(dc::statemachine(mSMDebug), "AIStateMachine::begin_loop(" << state_str(base_state) << ") [" << (void*)this << "]");
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "aithreadsafe.h"
|
||||
#include <llpointer.h>
|
||||
#include "lltimer.h"
|
||||
#include <list>
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
@@ -98,11 +99,143 @@ class AIEngine
|
||||
extern AIEngine gMainThreadEngine;
|
||||
extern AIEngine gStateMachineThreadEngine;
|
||||
|
||||
#ifndef STATE_MACHINE_PROFILING
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
#define STATE_MACHINE_PROFILING 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class AIStateMachine : public LLThreadSafeRefCount
|
||||
{
|
||||
public:
|
||||
typedef U32 state_type; //!< The type of run_state
|
||||
|
||||
// A simple timer class that will calculate time delta between ctor and GetTimerData call.
|
||||
// Time data is stored as a nested TimeData object.
|
||||
// If STATE_MACHINE_PROFILING is defined then a stack of all StateTimers from root is maintained for debug output.
|
||||
class StateTimerBase
|
||||
{
|
||||
public:
|
||||
class TimeData
|
||||
{
|
||||
friend class StateTimerBase;
|
||||
public:
|
||||
TimeData() : mStart(-1), mEnd(-1) {}
|
||||
U64 GetDuration() { return mEnd - mStart; }
|
||||
private:
|
||||
U64 mStart, mEnd;
|
||||
|
||||
#if !STATE_MACHINE_PROFILING
|
||||
TimeData(const std::string& name) : mStart(get_clock_count()), mEnd(get_clock_count()) {}
|
||||
#else
|
||||
TimeData(const std::string& name) : mName(name), mStart(get_clock_count()), mEnd(get_clock_count()) {}
|
||||
void DumpTimer(std::ostringstream& msg, std::string prefix);
|
||||
std::vector<TimeData> mChildren;
|
||||
std::string mName;
|
||||
static TimeData sRoot;
|
||||
#endif
|
||||
};
|
||||
#if !STATE_MACHINE_PROFILING
|
||||
StateTimerBase(const std::string& name) : mData(name) {}
|
||||
~StateTimerBase() {}
|
||||
protected:
|
||||
TimeData mData;
|
||||
// Return a copy of the underlying timer data.
|
||||
// This allows the data live beyond the scope of the state timer.
|
||||
public:
|
||||
const TimeData GetTimerData()
|
||||
{
|
||||
mData.mEnd = get_clock_count(); //set mEnd to current time, since GetTimerData() will always be called before the dtor, obv.
|
||||
return mData;
|
||||
}
|
||||
#else
|
||||
protected:
|
||||
// Ctors/dtors are hidden. Only StateTimerRoot and StateTimer are permitted to access them.
|
||||
StateTimerBase() : mData(NULL) {}
|
||||
~StateTimerBase()
|
||||
{
|
||||
// If mData is null then the timer was not registered due to being in the wrong thread or the root timer wasn't in the expected state.
|
||||
if (!mData)
|
||||
return;
|
||||
mData->mEnd = get_clock_count();
|
||||
mTimerStack.pop_back();
|
||||
}
|
||||
|
||||
// Also hide internals from everything except StateTimerRoot and StateTimer
|
||||
bool AddAsRoot(const std::string& name)
|
||||
{
|
||||
|
||||
if (!is_main_thread())
|
||||
return true; //Ignoring this timer, but pretending it was added.
|
||||
if (!mTimerStack.empty())
|
||||
return false;
|
||||
TimeData::sRoot = TimeData(name);
|
||||
mData = &TimeData::sRoot;
|
||||
mData->mChildren.clear();
|
||||
mTimerStack.push_back(this);
|
||||
return true;
|
||||
}
|
||||
bool AddAsChild(const std::string& name)
|
||||
{
|
||||
if (!is_main_thread())
|
||||
return true; //Ignoring this timer, but pretending it was added.
|
||||
if (mTimerStack.empty())
|
||||
return false;
|
||||
mTimerStack.back()->mData->mChildren.push_back(TimeData(name));
|
||||
mData = &mTimerStack.back()->mData->mChildren.back();
|
||||
mTimerStack.push_back(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
TimeData* mData;
|
||||
static std::vector<StateTimerBase*> mTimerStack;
|
||||
|
||||
public:
|
||||
// Debug spew
|
||||
static void DumpTimers(std::ostringstream& msg)
|
||||
{
|
||||
TimeData::sRoot.DumpTimer(msg, "");
|
||||
}
|
||||
|
||||
// Return a copy of the underlying timer data.
|
||||
// This allows the data live beyond the scope of the state timer.
|
||||
const TimeData GetTimerData() const
|
||||
{
|
||||
if (mData)
|
||||
{
|
||||
TimeData ret = *mData;
|
||||
ret.mEnd = get_clock_count(); //set mEnd to current time, since GetTimerData() will always be called before the dtor, obv.
|
||||
return ret;
|
||||
}
|
||||
return TimeData();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
public:
|
||||
#if !STATE_MACHINE_PROFILING
|
||||
typedef StateTimerBase StateTimerRoot;
|
||||
typedef StateTimerBase StateTimer;
|
||||
#else
|
||||
class StateTimerRoot : public StateTimerBase
|
||||
{ //A StateTimerRoot can become a child if a root already exists.
|
||||
public:
|
||||
StateTimerRoot(const std::string& name)
|
||||
{
|
||||
if(!AddAsRoot(name))
|
||||
AddAsChild(name);
|
||||
}
|
||||
};
|
||||
class StateTimer : public StateTimerBase
|
||||
{ //A StateTimer can never become a root
|
||||
public:
|
||||
StateTimer(const std::string& name)
|
||||
{
|
||||
AddAsChild(name);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
protected:
|
||||
// The type of event that causes multiplex() to be called.
|
||||
enum event_type {
|
||||
@@ -197,7 +330,7 @@ class AIStateMachine : public LLThreadSafeRefCount
|
||||
bool mDebugAdvanceStatePending; // True while advance_state() was called by not handled yet.
|
||||
bool mDebugRefCalled; // True when ref() is called (or will be called within the critial area of mMultiplexMutex).
|
||||
#endif
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
#ifdef CWDEBUG
|
||||
protected:
|
||||
bool mSMDebug; // Print debug output only when true.
|
||||
#endif
|
||||
@@ -210,7 +343,7 @@ class AIStateMachine : public LLThreadSafeRefCount
|
||||
mThreadId(AIThreadID::none), mDebugLastState(bs_killed), mDebugShouldRun(false), mDebugAborted(false), mDebugContPending(false),
|
||||
mDebugSetStatePending(false), mDebugAdvanceStatePending(false), mDebugRefCalled(false),
|
||||
#endif
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
#ifdef CWDEBUG
|
||||
mSMDebug(debug),
|
||||
#endif
|
||||
mRuntime(0)
|
||||
@@ -295,13 +428,16 @@ class AIStateMachine : public LLThreadSafeRefCount
|
||||
|
||||
// Return stringified state, for debugging purposes.
|
||||
char const* state_str(base_state_type state);
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
#ifdef CWDEBUG
|
||||
char const* event_str(event_type event);
|
||||
#endif
|
||||
|
||||
void add(U64 count) { mRuntime += count; }
|
||||
U64 getRuntime(void) const { return mRuntime; }
|
||||
|
||||
// For diagnostics. Every derived class must override this.
|
||||
virtual const char* getName() const = 0;
|
||||
|
||||
protected:
|
||||
virtual void initialize_impl(void) = 0;
|
||||
virtual void multiplex_impl(state_type run_state) = 0;
|
||||
|
||||
@@ -182,7 +182,7 @@ class AIStateMachineThreadBase : public AIStateMachine {
|
||||
|
||||
protected:
|
||||
AIStateMachineThreadBase(CWD_ONLY(bool debug))
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
#ifdef CWDEBUG
|
||||
: AIStateMachine(debug)
|
||||
#endif
|
||||
{ }
|
||||
@@ -222,7 +222,7 @@ class AIStateMachineThread : public AIStateMachineThreadBase {
|
||||
public:
|
||||
// Constructor.
|
||||
AIStateMachineThread(CWD_ONLY(bool debug))
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
#ifdef CWDEBUG
|
||||
: AIStateMachineThreadBase(debug)
|
||||
#endif
|
||||
{
|
||||
@@ -232,6 +232,13 @@ class AIStateMachineThread : public AIStateMachineThreadBase {
|
||||
// Accessor.
|
||||
THREAD_IMPL& thread_impl(void) { return mThreadImpl; }
|
||||
|
||||
/*virtual*/ const char* getName() const
|
||||
{
|
||||
#define STRIZE(arg) #arg
|
||||
return "AIStateMachineThread<"STRIZE(THREAD_IMPL)">";
|
||||
#undef STRIZE
|
||||
}
|
||||
|
||||
protected:
|
||||
/*virtual*/ AIThreadImpl& impl(void) { return mThreadImpl; }
|
||||
};
|
||||
|
||||
@@ -77,7 +77,7 @@ class AITimer : public AIStateMachine {
|
||||
|
||||
public:
|
||||
AITimer(CWD_ONLY(bool debug = false)) :
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
#ifdef CWDEBUG
|
||||
AIStateMachine(debug),
|
||||
#endif
|
||||
mInterval(0) { DoutEntering(dc::statemachine(mSMDebug), "AITimer(void) [" << (void*)this << "]"); }
|
||||
@@ -98,6 +98,8 @@ class AITimer : public AIStateMachine {
|
||||
*/
|
||||
F64 getInterval(void) const { return mInterval; }
|
||||
|
||||
/*virtual*/ const char* getName() const { return "AITimer"; }
|
||||
|
||||
protected:
|
||||
// Call finish() (or abort()), not delete.
|
||||
/*virtual*/ ~AITimer() { DoutEntering(dc::statemachine(mSMDebug), "~AITimer() [" << (void*)this << "]"); mFrameTimer.cancel(); }
|
||||
|
||||
@@ -54,6 +54,9 @@ if (WINDOWS)
|
||||
# Remove default /Zm1000 flag that cmake inserts
|
||||
string (REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
|
||||
# Always use /Zm140
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm140")
|
||||
|
||||
# Don't build DLLs.
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
|
||||
@@ -246,30 +249,28 @@ endif (LINUX)
|
||||
|
||||
|
||||
if (DARWIN)
|
||||
add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE)
|
||||
set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
|
||||
add_definitions(-DLL_DARWIN=1)
|
||||
set(CMAKE_CXX_LINK_FLAGS "-Wl,-no_compact_unwind -Wl,-headerpad_max_install_names,-search_paths_first")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-branch")
|
||||
# NOTE: it's critical that the optimization flag is put in front.
|
||||
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
# NOTE: it's critical that the optimization flag is put in front.
|
||||
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -msse3")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3")
|
||||
endif()
|
||||
set(DARWIN_extra_cstar_flags "-g")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags} -ftemplate-depth=256")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DARWIN_extra_cstar_flags}")
|
||||
# NOTE: it's critical that the optimization flag is put in front.
|
||||
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS SSE3)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL -O3)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -msse3 ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -msse3 ${CMAKE_C_FLAGS_RELEASE}")
|
||||
if (XCODE_VERSION GREATER 4.2)
|
||||
set(ENABLE_SIGNING TRUE)
|
||||
set(SIGNING_IDENTITY "Developer ID Application: Linden Research, Inc.")
|
||||
endif (XCODE_VERSION GREATER 4.2)
|
||||
endif (DARWIN)
|
||||
|
||||
|
||||
|
||||
if (LINUX OR DARWIN)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
add_definitions(-DLL_GNUC=1)
|
||||
@@ -277,13 +278,11 @@ if (LINUX OR DARWIN)
|
||||
set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
add_definitions(-DLL_CLANG=1)
|
||||
set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-tautological-compare -Wno-char-subscripts -Wno-gnu -Wno-logical-op-parentheses -Wno-non-virtual-dtor")
|
||||
set(UNIX_WARNINGS "${UNIX_WARNINGS} -Woverloaded-virtual -Wno-parentheses-equality -Wno-reorder -Wno-unused-function -Wno-unused-value -Wno-unused-variable")
|
||||
set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-tautological-compare -Wno-char-subscripts -Wno-gnu -Wno-logical-op-parentheses -Wno-logical-not-parentheses -Wno-non-virtual-dtor -Wno-deprecated")
|
||||
set(UNIX_WARNINGS "${UNIX_WARNINGS} -Woverloaded-virtual -Wno-parentheses-equality -Wno-reorder -Wno-unused-function -Wno-unused-value -Wno-unused-variable -Wno-unused-private-field -Wno-parentheses")
|
||||
set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS}")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||
add_definitions(-DLL_ICC=1)
|
||||
set(UNIX_WARNINGS "-wd327 -wd597 -wd858")
|
||||
set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS}")
|
||||
endif ()
|
||||
|
||||
if (NOT DISABLE_FATAL_WARNINGS)
|
||||
|
||||
@@ -52,6 +52,29 @@ if (DARWIN)
|
||||
)
|
||||
endif (DARWIN)
|
||||
|
||||
if (LINUX)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/newview/linux_tools/wrapper.sh.in
|
||||
${CMAKE_SOURCE_DIR}/newview/linux_tools/wrapper.sh
|
||||
@ONLY
|
||||
)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/newview/linux_tools/handle_secondlifeprotocol.sh.in
|
||||
${CMAKE_SOURCE_DIR}/newview/linux_tools/handle_secondlifeprotocol.sh
|
||||
@ONLY
|
||||
)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/newview/linux_tools/install.sh.in
|
||||
${CMAKE_SOURCE_DIR}/newview/linux_tools/install.sh
|
||||
@ONLY
|
||||
)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/newview/linux_tools/refresh_desktop_app_entry.sh.in
|
||||
${CMAKE_SOURCE_DIR}/newview/linux_tools/refresh_desktop_app_entry.sh
|
||||
@ONLY
|
||||
)
|
||||
endif (LINUX)
|
||||
|
||||
# Compose the version.
|
||||
set(viewer_VERSION "${vMAJOR}.${vMINOR}.${vPATCH}.${vBUILD}")
|
||||
if (viewer_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")
|
||||
|
||||
@@ -16,11 +16,14 @@ endif(WORD_SIZE EQUAL 32)
|
||||
|
||||
set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-win32")
|
||||
set(vivox_files
|
||||
SLVoice.exe
|
||||
alut.dll
|
||||
vivoxsdk.dll
|
||||
ca-bundle.crt
|
||||
libsndfile-1.dll
|
||||
ortp.dll
|
||||
wrap_oal.dll
|
||||
SLVoice.exe
|
||||
vivoxoal.dll
|
||||
vivoxplatform.dll
|
||||
vivoxsdk.dll
|
||||
zlib1.dll
|
||||
)
|
||||
copy_if_different(
|
||||
${vivox_src_dir}
|
||||
|
||||
@@ -97,24 +97,54 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(DARWIN 1)
|
||||
|
||||
if(${CMAKE_GENERATOR} MATCHES "Xcode")
|
||||
#SDK Compiler and Deployment targets for XCode
|
||||
if (${XCODE_VERSION} VERSION_LESS 4.0.0)
|
||||
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5)
|
||||
else (${XCODE_VERSION} VERSION_LESS 4.0.0)
|
||||
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
endif (${XCODE_VERSION} VERSION_LESS 4.0.0)
|
||||
else(${CMAKE_GENERATOR} MATCHES "Xcode")
|
||||
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
endif(${CMAKE_GENERATOR} MATCHES "Xcode")
|
||||
execute_process(
|
||||
COMMAND sh -c "xcodebuild -version | grep Xcode | cut -d ' ' -f2 | cut -d'.' -f1-2"
|
||||
OUTPUT_VARIABLE XCODE_VERSION )
|
||||
string(REGEX REPLACE "(\r?\n)+$" "" XCODE_VERSION "${XCODE_VERSION}")
|
||||
|
||||
# # To support a different SDK update these Xcode settings:
|
||||
# if (XCODE_VERSION GREATER 4.9) # (Which would be 5.0+)
|
||||
# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
|
||||
# set(CMAKE_OSX_SYSROOT macosx10.9)
|
||||
# else (XCODE_VERION GREATER 4.9)
|
||||
# if (XCODE_VERSION GREATER 4.5)
|
||||
# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
|
||||
# set(CMAKE_OSX_SYSROOT macosx10.8)
|
||||
# else (XCODE_VERSION GREATER 4.5)
|
||||
# if (XCODE_VERSION GREATER 4.2)
|
||||
# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
# set(CMAKE_OSX_SYSROOT macosx10.7)
|
||||
# else (XCODE_VERSION GREATER 4.2)
|
||||
# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
# set(CMAKE_OSX_SYSROOT macosx10.7)
|
||||
# endif (XCODE_VERSION GREATER 4.2)
|
||||
# endif (XCODE_VERSION GREATER 4.5)
|
||||
# endif (XCODE_VERSION GREATER 4.9)
|
||||
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
|
||||
# Hardcode SDK we build against until we can test and allow newer ones
|
||||
# as autodetected in the code above
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
set(CMAKE_OSX_SYSROOT macosx10.6)
|
||||
|
||||
# Support for Unix Makefiles generator
|
||||
if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
|
||||
execute_process(COMMAND xcodebuild -version -sdk "${CMAKE_OSX_SYSROOT}" Path | head -n 1 OUTPUT_VARIABLE CMAKE_OSX_SYSROOT)
|
||||
string(REGEX REPLACE "(\r?\n)+$" "" CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT}")
|
||||
endif (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
|
||||
|
||||
# LLVM-GCC has been removed in Xcode5
|
||||
if (XCODE_VERSION GREATER 4.9)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0")
|
||||
else (XCODE_VERSION GREATER 4.9)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
|
||||
endif (XCODE_VERSION GREATER 4.9)
|
||||
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym)
|
||||
|
||||
message(STATUS "Xcode version: ${XCODE_VERSION}")
|
||||
message(STATUS "OSX sysroot: ${CMAKE_OSX_SYSROOT}")
|
||||
message(STATUS "OSX deployment target: ${CMAKE_OSX_DEPLOYMENT_TARGET}")
|
||||
|
||||
# Build only for i386 by default, system default on MacOSX 10.6 is x86_64
|
||||
set(CMAKE_OSX_ARCHITECTURES i386)
|
||||
set(ARCH i386)
|
||||
|
||||
@@ -28,97 +28,16 @@
|
||||
#ifndef CWDEBUG
|
||||
|
||||
#ifdef DEBUG_CURLIO
|
||||
|
||||
// If CWDEBUG is not defined, but DEBUG_CURLIO is, then replace
|
||||
// some of the cwd macro's with something that generates viewer
|
||||
// specific debug output. Note that this generates a LOT of
|
||||
// output and should not normally be defined.
|
||||
|
||||
#include <string>
|
||||
#include "llpreprocessor.h"
|
||||
|
||||
namespace debug {
|
||||
namespace libcwd {
|
||||
|
||||
struct buf2str {
|
||||
buf2str(char const* buf, int size) : mBuf(buf), mSize(size) { }
|
||||
char const* mBuf;
|
||||
int mSize;
|
||||
};
|
||||
|
||||
struct libcwd_do_type {
|
||||
void on() const { }
|
||||
};
|
||||
extern LL_COMMON_API libcwd_do_type const libcw_do;
|
||||
|
||||
} // namespace libcwd
|
||||
|
||||
enum print_thread_id_t { print_thread_id };
|
||||
inline void init() { }
|
||||
struct Indent {
|
||||
int M_indent;
|
||||
static ll_thread_local int S_indentation;
|
||||
enum LL_COMMON_API print_nt { print };
|
||||
LL_COMMON_API Indent(int indent);
|
||||
LL_COMMON_API ~Indent();
|
||||
};
|
||||
|
||||
extern LL_COMMON_API std::ostream& operator<<(std::ostream& os, libcwd::buf2str const& b2s);
|
||||
extern LL_COMMON_API std::ostream& operator<<(std::ostream& os, Indent::print_nt);
|
||||
extern LL_COMMON_API std::ostream& operator<<(std::ostream& os, print_thread_id_t);
|
||||
|
||||
namespace dc {
|
||||
|
||||
struct fake_channel {
|
||||
int mOn;
|
||||
char const* mLabel;
|
||||
fake_channel(int on, char const* label) : mOn(on), mLabel(label) { }
|
||||
fake_channel(void) : mOn(0) { }
|
||||
fake_channel& operator()(bool) { return *this; }
|
||||
fake_channel const& operator()(bool) const { return *this; }
|
||||
bool is_on() const { return !!mOn; }
|
||||
bool is_off() const { return !mOn; }
|
||||
void on() const { }
|
||||
void off() const { }
|
||||
};
|
||||
extern LL_COMMON_API fake_channel const warning;
|
||||
extern LL_COMMON_API fake_channel const curl;
|
||||
extern LL_COMMON_API fake_channel const curlio;
|
||||
extern LL_COMMON_API fake_channel const curltr;
|
||||
extern LL_COMMON_API fake_channel const statemachine;
|
||||
extern LL_COMMON_API fake_channel const notice;
|
||||
extern LL_COMMON_API fake_channel const snapshot;
|
||||
|
||||
} // namespace dc
|
||||
} // namespace debug
|
||||
|
||||
#define LIBCWD_DEBUG_CHANNELS debug
|
||||
#define LibcwDoutScopeBegin(a, b, c) do { using namespace debug; using namespace debug::libcwd; llinfos_nf << print_thread_id << (c).mLabel << ": " << Indent::print;
|
||||
#define LibcwDoutStream llcont
|
||||
#define LibcwDoutScopeEnd llcont << llendl; } while(0)
|
||||
|
||||
#define Debug(x) do { using namespace debug; using namespace debug::libcwd; x; } while(0)
|
||||
#define Dout(a, b) do { using namespace debug; using namespace debug::libcwd; if ((a).mOn) { llinfos_nf << print_thread_id << (a).mLabel << ": " << Indent::print << b << llendl; } } while(0)
|
||||
#define DoutEntering(a, b) \
|
||||
int __slviewer_debug_indentation = 2; \
|
||||
{ \
|
||||
using namespace debug; \
|
||||
using namespace debug::libcwd; \
|
||||
if ((a).mOn) \
|
||||
llinfos_nf << print_thread_id << (a).mLabel << ": " << Indent::print << "Entering " << b << llendl; \
|
||||
else \
|
||||
__slviewer_debug_indentation = 0; \
|
||||
} \
|
||||
debug::Indent __slviewer_debug_indent(__slviewer_debug_indentation);
|
||||
|
||||
#else // !DEBUG_CURLIO
|
||||
#error DEBUG_CURLIO is not supported without libcwd.
|
||||
// In order to use DEBUG_CURLIO you must install and use libcwd.
|
||||
// Download libcwd:
|
||||
// git clone https://github.com/CarloWood/libcwd.git
|
||||
#endif
|
||||
|
||||
#define Debug(x)
|
||||
#define Dout(a, b)
|
||||
#define DoutEntering(a, b)
|
||||
|
||||
#endif // !DEBUG_CURLIO
|
||||
|
||||
#ifndef DOXYGEN // No need to document this. See http://libcwd.sourceforge.net/ for more info.
|
||||
|
||||
#include <iostream>
|
||||
@@ -392,6 +311,40 @@ void InstanceTracker<T>::dump(void)
|
||||
|
||||
} // namespace debug
|
||||
|
||||
template<class T>
|
||||
class AIDebugInstanceCounter
|
||||
{
|
||||
public:
|
||||
static int sInstanceCount;
|
||||
|
||||
protected:
|
||||
static void print_count(char const* name, int count, bool destruction);
|
||||
|
||||
AIDebugInstanceCounter()
|
||||
{
|
||||
print_count(typeid(T).name(), ++sInstanceCount, false);
|
||||
}
|
||||
AIDebugInstanceCounter(AIDebugInstanceCounter const&)
|
||||
{
|
||||
print_count(typeid(T).name(), ++sInstanceCount, false);
|
||||
}
|
||||
~AIDebugInstanceCounter()
|
||||
{
|
||||
print_count(typeid(T).name(), --sInstanceCount, true);
|
||||
}
|
||||
};
|
||||
|
||||
//static
|
||||
template<class T>
|
||||
int AIDebugInstanceCounter<T>::sInstanceCount;
|
||||
|
||||
//static
|
||||
template<class T>
|
||||
void AIDebugInstanceCounter<T>::print_count(char const* name, int count, bool destruction)
|
||||
{
|
||||
Dout(dc::notice, (destruction ? "Destructed " : "Constructing ") << name << ", now " << count << " instance" << ((count == 1) ? "." : "s."));
|
||||
}
|
||||
|
||||
//! Debugging macro.
|
||||
//
|
||||
// Print "Entering " << \a data to channel \a cntrl and increment
|
||||
|
||||
@@ -169,7 +169,7 @@ class PlatformSetup(object):
|
||||
raise
|
||||
|
||||
def parse_build_opts(self, arguments):
|
||||
opts, targets = getopt.getopt(arguments, 'o:', ['option='])
|
||||
opts, targets = getopt.getopt(arguments, 'D:o:', ['option='])
|
||||
build_opts = []
|
||||
for o, a in opts:
|
||||
if o in ('-o', '--option'):
|
||||
@@ -221,6 +221,7 @@ class UnixSetup(PlatformSetup):
|
||||
exe_suffixes = ('',)
|
||||
|
||||
def __init__(self):
|
||||
PlatformSetup.__init__(self)
|
||||
super(UnixSetup, self).__init__()
|
||||
self.generator = 'Unix Makefiles'
|
||||
|
||||
@@ -263,6 +264,7 @@ class UnixSetup(PlatformSetup):
|
||||
|
||||
class LinuxSetup(UnixSetup):
|
||||
def __init__(self):
|
||||
UnixSetup.__init__(self)
|
||||
super(LinuxSetup, self).__init__()
|
||||
try:
|
||||
self.debian_sarge = open('/etc/debian_version').read().strip() == '3.1'
|
||||
@@ -384,6 +386,7 @@ class LinuxSetup(UnixSetup):
|
||||
|
||||
class DarwinSetup(UnixSetup):
|
||||
def __init__(self):
|
||||
UnixSetup.__init__(self)
|
||||
super(DarwinSetup, self).__init__()
|
||||
self.generator = 'Xcode'
|
||||
|
||||
@@ -457,6 +460,7 @@ class WindowsSetup(PlatformSetup):
|
||||
exe_suffixes = ('.exe', '.bat', '.com')
|
||||
|
||||
def __init__(self):
|
||||
PlatformSetup.__init__(self)
|
||||
super(WindowsSetup, self).__init__()
|
||||
self._generator = None
|
||||
self.incredibuild = False
|
||||
@@ -497,7 +501,10 @@ class WindowsSetup(PlatformSetup):
|
||||
return 'win32'
|
||||
|
||||
def build_dirs(self):
|
||||
return ['build-' + self.generator]
|
||||
if self.word_size == 64:
|
||||
return ['build-' + self.generator + '-Win64']
|
||||
else:
|
||||
return ['build-' + self.generator]
|
||||
|
||||
def cmake_commandline(self, src_dir, build_dir, opts, simple):
|
||||
args = dict(
|
||||
@@ -605,15 +612,15 @@ class WindowsSetup(PlatformSetup):
|
||||
if environment == '':
|
||||
environment = self.find_visual_studio_express()
|
||||
if environment == '':
|
||||
environment = self.find_visual_studio_express_single()
|
||||
if environment == '':
|
||||
print >> sys.stderr, "Something went very wrong during build stage, could not find a Visual Studio?"
|
||||
else:
|
||||
build_dirs=self.build_dirs()
|
||||
print >> sys.stderr, "\nSolution generation complete, it can can now be found in:", build_dirs[0]
|
||||
print >> sys.stderr, "\nAs you are using an Express Visual Studio, the build step cannot be automated"
|
||||
print >> sys.stderr, "\nPlease see https://wiki.secondlife.com/wiki/Microsoft_Visual_Studio#Extra_steps_for_Visual_Studio_Express_editions for Visual Studio Express specific information"
|
||||
exit(0)
|
||||
environment = self.find_visual_studio_express_single()
|
||||
if environment == '':
|
||||
print >> sys.stderr, "Something went very wrong during build stage, could not find a Visual Studio?"
|
||||
else:
|
||||
build_dirs=self.build_dirs()
|
||||
print >> sys.stderr, "\nSolution generation complete, it can can now be found in:", build_dirs[0]
|
||||
print >> sys.stderr, "\nAs you are using an Express Visual Studio, the build step cannot be automated"
|
||||
print >> sys.stderr, "\nPlease see https://wiki.secondlife.com/wiki/Microsoft_Visual_Studio#Extra_steps_for_Visual_Studio_Express_editions for Visual Studio Express specific information"
|
||||
exit(0)
|
||||
|
||||
# devenv.com is CLI friendly, devenv.exe... not so much.
|
||||
return ('"%sdevenv.com" %s.sln /build %s' %
|
||||
@@ -655,7 +662,7 @@ class WindowsSetup(PlatformSetup):
|
||||
os.path.join(build_dir,'Singularity.sln') +
|
||||
' --config ' + self.build_type +
|
||||
' --startup secondlife-bin')
|
||||
print 'Running %r in %r' % (vstool_cmd, getcwd())
|
||||
print 'Running vstool %r in %r' % (vstool_cmd, getcwd())
|
||||
self.run(vstool_cmd)
|
||||
print >> open(stamp, 'w'), self.build_type
|
||||
|
||||
@@ -669,11 +676,11 @@ class WindowsSetup(PlatformSetup):
|
||||
if targets:
|
||||
for t in targets:
|
||||
cmd = '%s /project %s %s' % (build_cmd, t, ' '.join(opts))
|
||||
print 'Running %r in %r' % (cmd, d)
|
||||
print 'Running build(targets) %r in %r' % (cmd, d)
|
||||
self.run(cmd)
|
||||
else:
|
||||
cmd = '%s %s' % (build_cmd, ' '.join(opts))
|
||||
print 'Running %r in %r' % (cmd, d)
|
||||
print 'Running build %r in %r' % (cmd, d)
|
||||
self.run(cmd)
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
@@ -694,6 +701,8 @@ class CygwinSetup(WindowsSetup):
|
||||
project_name=self.project_name,
|
||||
word_size=self.word_size,
|
||||
)
|
||||
if self.word_size == 64:
|
||||
args["generator"] += r' Win64'
|
||||
#if simple:
|
||||
# return 'cmake %(opts)s "%(dir)s"' % args
|
||||
return ('cmake -G "%(generator)s" '
|
||||
|
||||
@@ -39,6 +39,7 @@ import shutil
|
||||
import sys
|
||||
import tarfile
|
||||
import errno
|
||||
import subprocess
|
||||
|
||||
def path_ancestors(path):
|
||||
drive, path = os.path.splitdrive(os.path.normpath(path))
|
||||
@@ -393,20 +394,19 @@ class LLManifest(object):
|
||||
debugging/informational purpoases, prints out the command's
|
||||
output as it is received."""
|
||||
print "Running command:", command
|
||||
fd = os.popen(command, 'r')
|
||||
fd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
lines = []
|
||||
while True:
|
||||
lines.append(fd.readline())
|
||||
lines.append(fd.stdout.readline())
|
||||
if lines[-1] == '':
|
||||
break
|
||||
else:
|
||||
print lines[-1],
|
||||
print lines[-1].rstrip('\n'),
|
||||
output = ''.join(lines)
|
||||
status = fd.close()
|
||||
if status:
|
||||
if fd.returncode:
|
||||
raise RuntimeError(
|
||||
"Command %s returned non-zero status (%s) \noutput:\n%s"
|
||||
% (command, status, output) )
|
||||
% (command, fd.returncode, output) )
|
||||
return output
|
||||
|
||||
def created_path(self, path):
|
||||
|
||||
@@ -317,7 +317,7 @@ namespace HACD
|
||||
bool m_addFacesPoints; //>! specifies whether to add faces points or not
|
||||
bool m_addExtraDistPoints; //>! specifies whether to add extra points for concave shapes or not
|
||||
|
||||
friend HACD * const CreateHACD(HeapManager * heapManager = 0);
|
||||
friend HACD * const CreateHACD(HeapManager * heapManager);
|
||||
friend void DestroyHACD(HACD * const hacd);
|
||||
};
|
||||
inline HACD * const CreateHACD(HeapManager * heapManager)
|
||||
|
||||
@@ -7,7 +7,7 @@ include(00-Common)
|
||||
include_directories(${LIBS_OPEN_DIR}/libhacd)
|
||||
|
||||
set (libndhacd_SOURCE_FILES
|
||||
LLConvexDecomposition.cpp
|
||||
llconvexdecomposition.cpp
|
||||
nd_hacdConvexDecomposition.cpp
|
||||
nd_hacdStructs.cpp
|
||||
nd_hacdUtils.cpp
|
||||
@@ -16,12 +16,12 @@ set (libndhacd_SOURCE_FILES
|
||||
)
|
||||
|
||||
set (libndhacd_HEADER_FILES
|
||||
LLConvexDecomposition.h
|
||||
llconvexdecomposition.h
|
||||
ndConvexDecomposition.h
|
||||
nd_hacdConvexDecomposition.h
|
||||
nd_hacdStructs.h
|
||||
nd_StructTracer.h
|
||||
LLConvexDecompositionStubImpl.h
|
||||
llconvexdecompositionstubimpl.h
|
||||
nd_EnterExitTracer.h
|
||||
nd_hacdDefines.h
|
||||
nd_hacdUtils.h
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file LLConvexDecomposition.cpp
|
||||
* @file llconvexdecomposition.cpp
|
||||
* @author falcon@lindenlab.com
|
||||
* @brief A stub implementation of LLConvexDecomposition interface
|
||||
*
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#include "nd_hacdConvexDecomposition.h"
|
||||
|
||||
#include "LLConvexDecomposition.h"
|
||||
#include "llconvexdecomposition.h"
|
||||
|
||||
|
||||
/*static */bool LLConvexDecomposition::s_isInitialized = false;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file LLConvexDecomposition.cpp
|
||||
* @file llconvexdecomposition.cpp
|
||||
* @brief LLConvexDecomposition interface definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file LLConvexDecompositionStubImpl.cpp
|
||||
* @file llconvexdecompositionstubimpl.cpp
|
||||
* @author falcon@lindenlab.com
|
||||
* @brief A stub implementation of LLConvexDecomposition
|
||||
*
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <memory>
|
||||
#include "LLConvexDecompositionStubImpl.h"
|
||||
#include "llconvexdecompositionstubimpl.h"
|
||||
|
||||
LLConvexDecomposition* LLConvexDecompositionImpl::getInstance()
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file LLConvexDecompositionStubImpl.h
|
||||
* @file llconvexdecompositionstubimpl.h
|
||||
* @author falcon@lindenlab.com
|
||||
* @brief A stub implementation of LLConvexDecomposition
|
||||
*
|
||||
@@ -29,7 +29,7 @@
|
||||
#ifndef LL_CONVEX_DECOMP_UTIL_H
|
||||
#define LL_CONVEX_DECOMP_UTIL_H
|
||||
|
||||
#include "LLConvexDecomposition.h"
|
||||
#include "llconvexdecomposition.h"
|
||||
|
||||
class LLConvexDecompositionImpl : public LLConvexDecomposition
|
||||
{
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
|
||||
#include "ndConvexDecomposition.h"
|
||||
#include "LLConvexDecomposition.h"
|
||||
#include "llconvexdecomposition.h"
|
||||
#include "nd_hacdStructs.h"
|
||||
|
||||
namespace ndStructTracer
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#ifndef ND_HACD_CONVEXDECOMP_H
|
||||
#define ND_HACD_CONVEXDECOMP_H
|
||||
|
||||
#include "LLConvexDecomposition.h"
|
||||
#include "llconvexdecomposition.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
|
||||
#include "nd_hacdStructs.h"
|
||||
#include "LLConvexDecomposition.h"
|
||||
|
||||
void DecompHull::clear()
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "nd_hacdDefines.h"
|
||||
#include "hacdHACD.h"
|
||||
#include "LLConvexDecomposition.h"
|
||||
#include "llconvexdecomposition.h"
|
||||
#include <vector>
|
||||
|
||||
struct LLCDHull;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#define ND_HACD_UTILS_H
|
||||
|
||||
#include "nd_hacdStructs.h"
|
||||
#include "LLConvexDecomposition.h"
|
||||
|
||||
tHACD* init( int nConcavity, int nClusters, int nMaxVerticesPerHull, double dMaxConnectDist, HACDDecoder *aData );
|
||||
DecompData decompose( tHACD *aHACD );
|
||||
|
||||
@@ -983,19 +983,19 @@ BOOL LLAvatarAppearance::loadSkeletonNode ()
|
||||
mRoot->addChild(mMeshLOD[MESH_ID_SKIRT]);
|
||||
mRoot->addChild(mMeshLOD[MESH_ID_HEAD]);
|
||||
|
||||
LLAvatarJoint *skull = (LLAvatarJoint*)mRoot->findJoint("mSkull");
|
||||
LLJoint *skull = mRoot->findJoint("mSkull");
|
||||
if (skull)
|
||||
{
|
||||
skull->addChild(mMeshLOD[MESH_ID_HAIR] );
|
||||
}
|
||||
|
||||
LLAvatarJoint *eyeL = (LLAvatarJoint*)mRoot->findJoint("mEyeLeft");
|
||||
LLJoint *eyeL = mRoot->findJoint("mEyeLeft");
|
||||
if (eyeL)
|
||||
{
|
||||
eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] );
|
||||
}
|
||||
|
||||
LLAvatarJoint *eyeR = (LLAvatarJoint*)mRoot->findJoint("mEyeRight");
|
||||
LLJoint *eyeR = mRoot->findJoint("mEyeRight");
|
||||
if (eyeR)
|
||||
{
|
||||
eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] );
|
||||
|
||||
@@ -105,8 +105,9 @@ void LLAvatarJoint::setValid( BOOL valid, BOOL recursive )
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
|
||||
joint->setValid(valid, TRUE);
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
if (joint)
|
||||
joint->setValid(valid, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +125,8 @@ void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive )
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
joint->setSkeletonComponents(comp, recursive);
|
||||
if (joint)
|
||||
joint->setSkeletonComponents(comp, recursive);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,8 +140,9 @@ void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive)
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
|
||||
joint->setVisible(visible, recursive);
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
if(joint)
|
||||
joint->setVisible(visible, recursive);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,7 +153,8 @@ void LLAvatarJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pix
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
joint->updateFaceSizes(num_vertices, num_indices, pixel_area);
|
||||
if (joint)
|
||||
joint->updateFaceSizes(num_vertices, num_indices, pixel_area);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +164,8 @@ void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind,
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
joint->updateFaceData(face, pixel_area, damp_wind, terse_update);
|
||||
if (joint)
|
||||
joint->updateFaceData(face, pixel_area, damp_wind, terse_update);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +175,8 @@ void LLAvatarJoint::updateJointGeometry()
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
joint->updateJointGeometry();
|
||||
if (joint)
|
||||
joint->updateJointGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +190,9 @@ BOOL LLAvatarJoint::updateLOD(F32 pixel_area, BOOL activate)
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
if (!joint)
|
||||
continue;
|
||||
|
||||
F32 jointLOD = joint->getLOD();
|
||||
|
||||
if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD)
|
||||
@@ -213,7 +222,8 @@ void LLAvatarJoint::dump()
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
joint->dump();
|
||||
if (joint)
|
||||
joint->dump();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +270,7 @@ void LLAvatarJointCollisionVolume::renderCollision()
|
||||
updateWorldMatrix();
|
||||
|
||||
gGL.pushMatrix();
|
||||
gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] );
|
||||
gGL.multMatrix( mXform.getWorldMatrix() );
|
||||
|
||||
gGL.diffuseColor3f( 0.f, 0.f, 1.f );
|
||||
|
||||
|
||||
@@ -83,30 +83,28 @@ LLSkinJoint::~LLSkinJoint()
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLSkinJoint::setupSkinJoint()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint)
|
||||
void LLSkinJoint::setupSkinJoint( LLJoint *joint)
|
||||
{
|
||||
mRootToJointSkinOffset.clearVec();
|
||||
mRootToParentJointSkinOffset.clearVec();
|
||||
|
||||
// find the named joint
|
||||
mJoint = joint;
|
||||
if ( !mJoint )
|
||||
if (!(mJoint = joint))
|
||||
{
|
||||
llinfos << "Can't find joint" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
// compute the inverse root skin matrix
|
||||
mRootToJointSkinOffset.clearVec();
|
||||
|
||||
LLVector3 rootSkinOffset;
|
||||
while (joint)
|
||||
do
|
||||
{
|
||||
rootSkinOffset += joint->getSkinOffset();
|
||||
joint = (LLAvatarJoint*)joint->getParent();
|
||||
}
|
||||
mRootToJointSkinOffset -= joint->getSkinOffset();
|
||||
} while (joint = joint->getParent());
|
||||
|
||||
mRootToJointSkinOffset = -rootSkinOffset;
|
||||
mRootToParentJointSkinOffset = mRootToJointSkinOffset;
|
||||
mRootToParentJointSkinOffset += mJoint->getSkinOffset();
|
||||
|
||||
return TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -307,15 +305,14 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh )
|
||||
for (jn = 0; jn < numJointNames; jn++)
|
||||
{
|
||||
//llinfos << "Setting up joint " << jointNames[jn] << llendl;
|
||||
LLAvatarJoint* joint = (LLAvatarJoint*)(getRoot()->findJoint(jointNames[jn]) );
|
||||
mSkinJoints[jn].setupSkinJoint( joint );
|
||||
mSkinJoints[jn].setupSkinJoint( getRoot()->findJoint(jointNames[jn]) );
|
||||
}
|
||||
}
|
||||
|
||||
// setup joint array
|
||||
if (!mMesh->isLOD())
|
||||
{
|
||||
setupJoint((LLAvatarJoint*)getRoot());
|
||||
setupJoint(getRoot());
|
||||
}
|
||||
|
||||
// llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl;
|
||||
@@ -324,7 +321,7 @@ void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh )
|
||||
//-----------------------------------------------------------------------------
|
||||
// setupJoint()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint)
|
||||
void LLAvatarJointMesh::setupJoint(LLJoint* current_joint)
|
||||
{
|
||||
// llinfos << "Mesh: " << getName() << llendl;
|
||||
|
||||
@@ -345,7 +342,7 @@ void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint)
|
||||
if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix())
|
||||
{
|
||||
// ...then just add ourselves
|
||||
LLAvatarJoint* jointp = js.mJoint;
|
||||
LLJoint* jointp = js.mJoint;
|
||||
mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
|
||||
// llinfos << "joint " << joint_count << js.mJoint->getName() << llendl;
|
||||
// joint_count++;
|
||||
@@ -366,8 +363,9 @@ void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint)
|
||||
for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
|
||||
iter != current_joint->mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
|
||||
setupJoint(child_joint);
|
||||
LLAvatarJoint* child_joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
if(child_joint)
|
||||
setupJoint(child_joint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ class LLSkinJoint
|
||||
public:
|
||||
LLSkinJoint();
|
||||
~LLSkinJoint();
|
||||
BOOL setupSkinJoint( LLAvatarJoint *joint);
|
||||
void setupSkinJoint( LLJoint *joint);
|
||||
|
||||
LLAvatarJoint *mJoint;
|
||||
LLJoint* mJoint;
|
||||
LLVector3 mRootToJointSkinOffset;
|
||||
LLVector3 mRootToParentJointSkinOffset;
|
||||
};
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
void setMesh( LLPolyMesh *mesh );
|
||||
|
||||
// Sets up joint matrix data for rendering
|
||||
void setupJoint(LLAvatarJoint* current_joint);
|
||||
void setupJoint(LLJoint* current_joint);
|
||||
|
||||
// Sets ID for picking
|
||||
void setMeshID( S32 id ) {mMeshID = id;}
|
||||
|
||||
@@ -231,9 +231,9 @@ BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices )
|
||||
mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a));
|
||||
mBaseNormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a));
|
||||
mBaseBinormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a));
|
||||
mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2));
|
||||
mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2));
|
||||
mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32));
|
||||
mTexCoords = (LLVector2*) ll_aligned_malloc_16((numVertices+numVertices%2)*sizeof(LLVector2));
|
||||
mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16((numVertices+numVertices%2)*sizeof(LLVector2));
|
||||
mWeights = (F32*) ll_aligned_malloc_16(((numVertices)*sizeof(F32)+0xF) & ~0xF);
|
||||
for (i = 0; i < numVertices; i++)
|
||||
{
|
||||
mBaseCoords[i].clear();
|
||||
|
||||
@@ -146,10 +146,10 @@ public:
|
||||
class LLJointRenderData
|
||||
{
|
||||
public:
|
||||
LLJointRenderData(const LLMatrix4* world_matrix, LLSkinJoint* skin_joint) : mWorldMatrix(world_matrix), mSkinJoint(skin_joint) {}
|
||||
LLJointRenderData(const LLMatrix4a* world_matrix, LLSkinJoint* skin_joint) : mWorldMatrix(world_matrix), mSkinJoint(skin_joint) {}
|
||||
~LLJointRenderData(){}
|
||||
|
||||
const LLMatrix4* mWorldMatrix;
|
||||
const LLMatrix4a* mWorldMatrix;
|
||||
LLSkinJoint* mSkinJoint;
|
||||
};
|
||||
|
||||
|
||||
@@ -154,13 +154,13 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
|
||||
for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
|
||||
iter != joint->mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
|
||||
if (child_joint->inheritScale())
|
||||
{
|
||||
LLVector3 childDeformation = LLVector3(child_joint->getScale());
|
||||
childDeformation.scaleVec(bone_info->mScaleDeformation);
|
||||
mJointScales[child_joint] = childDeformation;
|
||||
}
|
||||
LLAvatarJoint* child_joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
if (child_joint && child_joint->inheritScale())
|
||||
{
|
||||
LLVector3 childDeformation = LLVector3(child_joint->getScale());
|
||||
childDeformation.scaleVec(bone_info->mScaleDeformation);
|
||||
mJointScales[child_joint] = childDeformation;
|
||||
}
|
||||
}
|
||||
|
||||
if (bone_info->mHasPositionDeformation)
|
||||
|
||||
@@ -68,7 +68,16 @@ class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo
|
||||
{
|
||||
friend class LLPolySkeletalDistortion;
|
||||
public:
|
||||
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
|
||||
LLPolySkeletalDistortionInfo();
|
||||
/*virtual*/ ~LLPolySkeletalDistortionInfo() {};
|
||||
|
||||
@@ -77,12 +86,12 @@ public:
|
||||
protected:
|
||||
typedef std::vector<LLPolySkeletalBoneInfo> bone_info_list_t;
|
||||
bone_info_list_t mBoneInfoList;
|
||||
};
|
||||
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLPolySkeletalDeformation
|
||||
// A set of joint scale data for deforming the avatar mesh
|
||||
//-----------------------------------------------------------------------------
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLPolySkeletalDistortion : public LLViewerVisualParam
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
|
||||
#ifndef LL_LLAUDIODECODEMGR_H
|
||||
#define LL_LLAUDIODECODEMG_H
|
||||
#define LL_LLAUDIODECODEMGR_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ set(llcharacter_SOURCE_FILES
|
||||
lljointsolverrp3.cpp
|
||||
llkeyframefallmotion.cpp
|
||||
llkeyframemotion.cpp
|
||||
llkeyframemotionparam.cpp
|
||||
llkeyframestandmotion.cpp
|
||||
llkeyframewalkmotion.cpp
|
||||
llmotion.cpp
|
||||
@@ -57,7 +56,6 @@ set(llcharacter_HEADER_FILES
|
||||
lljointstate.h
|
||||
llkeyframefallmotion.h
|
||||
llkeyframemotion.h
|
||||
llkeyframemotionparam.h
|
||||
llkeyframestandmotion.h
|
||||
llkeyframewalkmotion.h
|
||||
llmotion.h
|
||||
|
||||
@@ -72,21 +72,11 @@ LLCharacter::~LLCharacter()
|
||||
delete param;
|
||||
}
|
||||
|
||||
U32 i ;
|
||||
U32 size = sInstances.size() ;
|
||||
for(i = 0 ; i < size ; i++)
|
||||
{
|
||||
if(sInstances[i] == this)
|
||||
{
|
||||
break ;
|
||||
}
|
||||
}
|
||||
bool erased = vector_replace_with_last(sInstances,this);
|
||||
|
||||
llassert_always(i < size) ;
|
||||
llassert_always(erased) ;
|
||||
|
||||
llassert_always(sAllowInstancesChange) ;
|
||||
sInstances[i] = sInstances[size - 1] ;
|
||||
sInstances.pop_back() ;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +126,6 @@ LLMotion* LLCharacter::findMotion( const LLUUID &id )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// createMotion()
|
||||
// NOTE: Always assign the result to a LLPointer!
|
||||
//-----------------------------------------------------------------------------
|
||||
LLMotion* LLCharacter::createMotion( const LLUUID &id )
|
||||
{
|
||||
@@ -195,11 +184,26 @@ void LLCharacter::updateMotions(e_update_t update_type)
|
||||
{
|
||||
if (update_type == HIDDEN_UPDATE)
|
||||
{
|
||||
//<singu>
|
||||
// Keep updating avatars that have at least one motion that is synchronized with a still running motion.
|
||||
// This call tells the other controllers that we are in principle hidden.
|
||||
// It returns false if we need to keep updating anyway.
|
||||
if (!mMotionController.hidden(true))
|
||||
{
|
||||
mMotionController.updateMotions(LLCharacter::NORMAL_UPDATE);
|
||||
return;
|
||||
}
|
||||
//</singu>
|
||||
LLFastTimer t(FTM_UPDATE_HIDDEN_ANIMATION);
|
||||
mMotionController.updateMotionsMinimal();
|
||||
}
|
||||
else
|
||||
{
|
||||
//<singu>
|
||||
// This call tells the other controllers that we are visible and that they need
|
||||
// to keep updating if they are synchronized with us, even if they are hidden.
|
||||
mMotionController.hidden(false);
|
||||
//</singu>
|
||||
LLFastTimer t(FTM_UPDATE_ANIMATION);
|
||||
// unpause if the number of outstanding pause requests has dropped to the initial one
|
||||
if (mMotionController.isPaused() && mPauseRequest->getNumRefs() == 1)
|
||||
@@ -529,3 +533,17 @@ LLAnimPauseRequest LLCharacter::requestPause()
|
||||
return mPauseRequest;
|
||||
}
|
||||
|
||||
void LLCharacter::requestPause(std::vector<LLAnimPauseRequest>& avatar_pause_handles)
|
||||
{
|
||||
mMotionController.pauseAllMotions();
|
||||
avatar_pause_handles.push_back(mPauseRequest);
|
||||
}
|
||||
|
||||
void LLCharacter::pauseAllSyncedCharacters(std::vector<LLAnimPauseRequest>& avatar_pause_handles)
|
||||
{
|
||||
// Pause this avatar.
|
||||
requestPause(avatar_pause_handles);
|
||||
// Also pause all avatars with synchronized motions.
|
||||
mMotionController.pauseAllSyncedCharacters(avatar_pause_handles);
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ public:
|
||||
|
||||
// is this motion active?
|
||||
BOOL isMotionActive( const LLUUID& id );
|
||||
bool isMotionActive(U32 bit) const { return mMotionController.isactive(bit); }
|
||||
|
||||
// Event handler for motion deactivation.
|
||||
// Called when a motion has completely stopped and has been deactivated.
|
||||
@@ -158,6 +159,8 @@ public:
|
||||
void updateMotions(e_update_t update_type);
|
||||
|
||||
LLAnimPauseRequest requestPause();
|
||||
void requestPause(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
|
||||
void pauseAllSyncedCharacters(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
|
||||
BOOL areAnimationsPaused() const { return mMotionController.isPaused(); }
|
||||
void setAnimTimeFactor(F32 factor) { mMotionController.setTimeFactor(factor); }
|
||||
void setTimeStep(F32 time_step) { mMotionController.setTimeStep(time_step); }
|
||||
|
||||
@@ -49,7 +49,7 @@ S32 LLEditingMotion::sHandPosePriority = 3;
|
||||
// LLEditingMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLEditingMotion::LLEditingMotion( const LLUUID &id) : LLMotion(id)
|
||||
LLEditingMotion::LLEditingMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_EDITING)
|
||||
{
|
||||
mCharacter = NULL;
|
||||
|
||||
@@ -155,7 +155,7 @@ BOOL LLEditingMotion::onActivate()
|
||||
mShoulderJoint.setRotation( mShoulderState->getJoint()->getRotation() );
|
||||
mElbowJoint.setRotation( mElbowState->getJoint()->getRotation() );
|
||||
|
||||
return TRUE;
|
||||
return AIMaskedMotion::onActivate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -256,12 +256,4 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLEditingMotion::onDeactivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLEditingMotion::onDeactivate()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// End
|
||||
|
||||
@@ -49,11 +49,11 @@
|
||||
// class LLEditingMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLEditingMotion :
|
||||
public LLMotion
|
||||
public AIMaskedMotion
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLEditingMotion(const LLUUID &id);
|
||||
LLEditingMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLEditingMotion();
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLEditingMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLEditingMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -107,9 +107,6 @@ public:
|
||||
// must return FALSE when the motion is completed.
|
||||
virtual BOOL onUpdate(F32 time, U8* joint_mask);
|
||||
|
||||
// called when a motion is deactivated
|
||||
virtual void onDeactivate();
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// joint states to be animated
|
||||
|
||||
@@ -61,7 +61,7 @@ const F32 HAND_MORPH_BLEND_TIME = 0.2f;
|
||||
// LLHandMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLHandMotion::LLHandMotion(const LLUUID &id) : LLMotion(id)
|
||||
LLHandMotion::LLHandMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_HAND_MOTION)
|
||||
{
|
||||
mCharacter = NULL;
|
||||
mLastTime = 0.f;
|
||||
@@ -112,7 +112,7 @@ BOOL LLHandMotion::onActivate()
|
||||
mCharacter->setVisualParamWeight(gHandPoseNames[mCurrentPose], 1.f);
|
||||
mCharacter->updateVisualParams();
|
||||
}
|
||||
return TRUE;
|
||||
return AIMaskedMotion::onActivate();
|
||||
}
|
||||
|
||||
|
||||
@@ -235,14 +235,6 @@ BOOL LLHandMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLHandMotion::onDeactivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLHandMotion::onDeactivate()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLHandMotion::getHandPoseName()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
// class LLHandMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLHandMotion :
|
||||
public LLMotion
|
||||
public AIMaskedMotion
|
||||
{
|
||||
public:
|
||||
typedef enum e_hand_pose
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
} eHandPose;
|
||||
|
||||
// Constructor
|
||||
LLHandMotion(const LLUUID &id);
|
||||
LLHandMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLHandMotion();
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLHandMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLHandMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -122,9 +122,6 @@ public:
|
||||
// must return FALSE when the motion is completed.
|
||||
virtual BOOL onUpdate(F32 time, U8* joint_mask);
|
||||
|
||||
// called when a motion is deactivated
|
||||
virtual void onDeactivate();
|
||||
|
||||
virtual BOOL canDeprecate() { return FALSE; }
|
||||
|
||||
static std::string getHandPoseName(eHandPose pose);
|
||||
|
||||
@@ -76,8 +76,8 @@ const F32 EYE_BLINK_TIME_DELTA = 0.005f; // time between one eye starting a blin
|
||||
// LLHeadRotMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLHeadRotMotion::LLHeadRotMotion(const LLUUID &id) :
|
||||
LLMotion(id),
|
||||
LLHeadRotMotion::LLHeadRotMotion(LLUUID const& id, LLMotionController* controller) :
|
||||
AIMaskedMotion(id, controller, ANIM_AGENT_HEAD_ROT),
|
||||
mCharacter(NULL),
|
||||
mTorsoJoint(NULL),
|
||||
mHeadJoint(NULL)
|
||||
@@ -104,7 +104,10 @@ LLHeadRotMotion::~LLHeadRotMotion()
|
||||
LLMotion::LLMotionInitStatus LLHeadRotMotion::onInitialize(LLCharacter *character)
|
||||
{
|
||||
if (!character)
|
||||
{
|
||||
llwarns << "character is NULL." << llendl;
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
mCharacter = character;
|
||||
|
||||
mPelvisJoint = character->getJoint("mPelvis");
|
||||
@@ -169,16 +172,6 @@ LLMotion::LLMotionInitStatus LLHeadRotMotion::onInitialize(LLCharacter *characte
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLHeadRotMotion::onActivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLHeadRotMotion::onActivate()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLHeadRotMotion::onUpdate()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -263,19 +256,11 @@ BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLHeadRotMotion::onDeactivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLHeadRotMotion::onDeactivate()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLEyeMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLEyeMotion::LLEyeMotion(const LLUUID &id) : LLMotion(id)
|
||||
LLEyeMotion::LLEyeMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_EYE)
|
||||
{
|
||||
mCharacter = NULL;
|
||||
mEyeJitterTime = 0.f;
|
||||
@@ -343,16 +328,6 @@ LLMotion::LLMotionInitStatus LLEyeMotion::onInitialize(LLCharacter *character)
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLEyeMotion::onActivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLEyeMotion::onActivate()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLEyeMotion::onUpdate()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -533,6 +508,8 @@ void LLEyeMotion::onDeactivate()
|
||||
{
|
||||
joint->setRotation(LLQuaternion::DEFAULT);
|
||||
}
|
||||
|
||||
AIMaskedMotion::onDeactivate();
|
||||
}
|
||||
|
||||
// End
|
||||
|
||||
@@ -46,11 +46,11 @@
|
||||
// class LLHeadRotMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLHeadRotMotion :
|
||||
public LLMotion
|
||||
public AIMaskedMotion
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLHeadRotMotion(const LLUUID &id);
|
||||
LLHeadRotMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLHeadRotMotion();
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLHeadRotMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLHeadRotMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -94,19 +94,11 @@ public:
|
||||
// must return true to indicate success and be available for activation
|
||||
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
|
||||
|
||||
// called when a motion is activated
|
||||
// must return TRUE to indicate success, or else
|
||||
// it will be deactivated
|
||||
virtual BOOL onActivate();
|
||||
|
||||
// called per time step
|
||||
// must return TRUE while it is active, and
|
||||
// must return FALSE when the motion is completed.
|
||||
virtual BOOL onUpdate(F32 time, U8* joint_mask);
|
||||
|
||||
// called when a motion is deactivated
|
||||
virtual void onDeactivate();
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// joint states to be animated
|
||||
@@ -129,11 +121,11 @@ public:
|
||||
// class LLEyeMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLEyeMotion :
|
||||
public LLMotion
|
||||
public AIMaskedMotion
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLEyeMotion(const LLUUID &id);
|
||||
LLEyeMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLEyeMotion();
|
||||
@@ -145,7 +137,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create( const LLUUID &id) { return new LLEyeMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLEyeMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -177,11 +169,6 @@ public:
|
||||
// must return true to indicate success and be available for activation
|
||||
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
|
||||
|
||||
// called when a motion is activated
|
||||
// must return TRUE to indicate success, or else
|
||||
// it will be deactivated
|
||||
virtual BOOL onActivate();
|
||||
|
||||
// called per time step
|
||||
// must return TRUE while it is active, and
|
||||
// must return FALSE when the motion is completed.
|
||||
|
||||
@@ -312,19 +312,15 @@ void LLJoint::setWorldPosition( const LLVector3& pos )
|
||||
return;
|
||||
}
|
||||
|
||||
LLMatrix4 temp_matrix = getWorldMatrix();
|
||||
temp_matrix.mMatrix[VW][VX] = pos.mV[VX];
|
||||
temp_matrix.mMatrix[VW][VY] = pos.mV[VY];
|
||||
temp_matrix.mMatrix[VW][VZ] = pos.mV[VZ];
|
||||
LLMatrix4a temp_matrix = getWorldMatrix();
|
||||
temp_matrix.setTranslate_affine(pos);
|
||||
|
||||
LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
|
||||
LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
|
||||
LLMatrix4a invParentWorldMatrix = mParent->getWorldMatrix();
|
||||
invParentWorldMatrix.invert();
|
||||
|
||||
temp_matrix *= invParentWorldMatrix;
|
||||
invParentWorldMatrix.mul(temp_matrix);
|
||||
|
||||
LLVector3 localPos( temp_matrix.mMatrix[VW][VX],
|
||||
temp_matrix.mMatrix[VW][VY],
|
||||
temp_matrix.mMatrix[VW][VZ] );
|
||||
LLVector3 localPos( invParentWorldMatrix.getRow<LLMatrix4a::ROW_TRANS>().getF32ptr() );
|
||||
|
||||
setPosition( localPos );
|
||||
}
|
||||
@@ -383,19 +379,19 @@ void LLJoint::setWorldRotation( const LLQuaternion& rot )
|
||||
this->setRotation( rot );
|
||||
return;
|
||||
}
|
||||
|
||||
LLMatrix4a parentWorldMatrix = mParent->getWorldMatrix();
|
||||
LLQuaternion2 rota(rot);
|
||||
LLMatrix4a temp_mat(rota);
|
||||
|
||||
LLMatrix4 temp_mat(rot);
|
||||
LLMatrix4a invParentWorldMatrix = mParent->getWorldMatrix();
|
||||
invParentWorldMatrix.setTranslate_affine(LLVector3(0.f));
|
||||
|
||||
LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
|
||||
parentWorldMatrix.mMatrix[VW][VX] = 0;
|
||||
parentWorldMatrix.mMatrix[VW][VY] = 0;
|
||||
parentWorldMatrix.mMatrix[VW][VZ] = 0;
|
||||
invParentWorldMatrix.invert();
|
||||
|
||||
LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
|
||||
invParentWorldMatrix.mul(temp_mat);
|
||||
|
||||
temp_mat *= invParentWorldMatrix;
|
||||
|
||||
setRotation(LLQuaternion(temp_mat));
|
||||
setRotation(LLQuaternion(LLMatrix4(invParentWorldMatrix.getF32ptr())));
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +421,7 @@ void LLJoint::setScale( const LLVector3& scale )
|
||||
//--------------------------------------------------------------------
|
||||
// getWorldMatrix()
|
||||
//--------------------------------------------------------------------
|
||||
const LLMatrix4 &LLJoint::getWorldMatrix()
|
||||
const LLMatrix4a &LLJoint::getWorldMatrix()
|
||||
{
|
||||
updateWorldMatrixParent();
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "lldarray.h"
|
||||
|
||||
const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15;
|
||||
const U32 LL_CHARACTER_MAX_JOINTS = 32; // must be divisible by 4!
|
||||
const U32 LL_CHARACTER_MAX_JOINTS = 32; // must be divisible by 16!
|
||||
const U32 LL_HAND_JOINT_NUM = 31;
|
||||
const U32 LL_FACE_JOINT_NUM = 30;
|
||||
const S32 LL_CHARACTER_MAX_PRIORITY = 7;
|
||||
@@ -162,7 +162,7 @@ public:
|
||||
void setScale( const LLVector3& scale );
|
||||
|
||||
// get/set world matrix
|
||||
const LLMatrix4 &getWorldMatrix();
|
||||
const LLMatrix4a &getWorldMatrix();
|
||||
void setWorldMatrix( const LLMatrix4& mat );
|
||||
|
||||
void updateWorldMatrixChildren();
|
||||
|
||||
@@ -171,12 +171,14 @@ void LLJointSolverRP3::solve()
|
||||
//-------------------------------------------------------------------------
|
||||
// get the poleVector in world space
|
||||
//-------------------------------------------------------------------------
|
||||
LLMatrix4 worldJointAParentMat;
|
||||
LLVector3 poleVec = mPoleVector;
|
||||
if ( mJointA->getParent() )
|
||||
{
|
||||
worldJointAParentMat = mJointA->getParent()->getWorldMatrix();
|
||||
LLVector4a pole_veca;
|
||||
pole_veca.load3(mPoleVector.mV);
|
||||
mJointA->getParent()->getWorldMatrix().rotate(pole_veca,pole_veca);
|
||||
poleVec.set(pole_veca.getF32ptr());
|
||||
}
|
||||
LLVector3 poleVec = rotate_vector( mPoleVector, worldJointAParentMat );
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// compute the following:
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
// LLKeyframeFallMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLKeyframeFallMotion::LLKeyframeFallMotion(const LLUUID &id) : LLKeyframeMotion(id)
|
||||
LLKeyframeFallMotion::LLKeyframeFallMotion(LLUUID const& id, LLMotionController* controller) : LLKeyframeMotion(id, controller)
|
||||
{
|
||||
mVelocityZ = 0.f;
|
||||
mCharacter = NULL;
|
||||
|
||||
@@ -47,7 +47,7 @@ class LLKeyframeFallMotion :
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLKeyframeFallMotion(const LLUUID &id);
|
||||
LLKeyframeFallMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLKeyframeFallMotion();
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLKeyframeFallMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLKeyframeFallMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@@ -84,38 +84,55 @@ LLKeyframeMotion::JointMotionList::~JointMotionList()
|
||||
for_each(mJointMotionArray.begin(), mJointMotionArray.end(), DeletePointer());
|
||||
}
|
||||
|
||||
U32 LLKeyframeMotion::JointMotionList::dumpDiagInfo()
|
||||
//Singu: add parameter 'silent'.
|
||||
U32 LLKeyframeMotion::JointMotionList::dumpDiagInfo(bool silent) const
|
||||
{
|
||||
S32 total_size = sizeof(JointMotionList);
|
||||
|
||||
for (U32 i = 0; i < getNumJointMotions(); i++)
|
||||
{
|
||||
LLKeyframeMotion::JointMotion* joint_motion_p = mJointMotionArray[i];
|
||||
LLKeyframeMotion::JointMotion const* joint_motion_p = mJointMotionArray[i];
|
||||
|
||||
llinfos << "\tJoint " << joint_motion_p->mJointName << llendl;
|
||||
if (!silent)
|
||||
{
|
||||
llinfos << "\tJoint " << joint_motion_p->mJointName << llendl;
|
||||
}
|
||||
if (joint_motion_p->mUsage & LLJointState::SCALE)
|
||||
{
|
||||
llinfos << "\t" << joint_motion_p->mScaleCurve.mNumKeys << " scale keys at "
|
||||
<< joint_motion_p->mScaleCurve.mNumKeys * sizeof(ScaleKey) << " bytes" << llendl;
|
||||
|
||||
if (!silent)
|
||||
{
|
||||
llinfos << "\t" << joint_motion_p->mScaleCurve.mNumKeys << " scale keys at "
|
||||
<< joint_motion_p->mScaleCurve.mNumKeys * sizeof(ScaleKey) << " bytes" << llendl;
|
||||
}
|
||||
total_size += joint_motion_p->mScaleCurve.mNumKeys * sizeof(ScaleKey);
|
||||
}
|
||||
if (joint_motion_p->mUsage & LLJointState::ROT)
|
||||
{
|
||||
llinfos << "\t" << joint_motion_p->mRotationCurve.mNumKeys << " rotation keys at "
|
||||
<< joint_motion_p->mRotationCurve.mNumKeys * sizeof(RotationKey) << " bytes" << llendl;
|
||||
|
||||
if (!silent)
|
||||
{
|
||||
llinfos << "\t" << joint_motion_p->mRotationCurve.mNumKeys << " rotation keys at "
|
||||
<< joint_motion_p->mRotationCurve.mNumKeys * sizeof(RotationKey) << " bytes" << llendl;
|
||||
}
|
||||
total_size += joint_motion_p->mRotationCurve.mNumKeys * sizeof(RotationKey);
|
||||
}
|
||||
if (joint_motion_p->mUsage & LLJointState::POS)
|
||||
{
|
||||
llinfos << "\t" << joint_motion_p->mPositionCurve.mNumKeys << " position keys at "
|
||||
<< joint_motion_p->mPositionCurve.mNumKeys * sizeof(PositionKey) << " bytes" << llendl;
|
||||
|
||||
if (!silent)
|
||||
{
|
||||
llinfos << "\t" << joint_motion_p->mPositionCurve.mNumKeys << " position keys at "
|
||||
<< joint_motion_p->mPositionCurve.mNumKeys * sizeof(PositionKey) << " bytes" << llendl;
|
||||
}
|
||||
total_size += joint_motion_p->mPositionCurve.mNumKeys * sizeof(PositionKey);
|
||||
}
|
||||
}
|
||||
llinfos << "Size: " << total_size << " bytes" << llendl;
|
||||
//Singu: Also add memory used by the constraints.
|
||||
S32 constraints_size = mConstraints.size() * sizeof(constraint_list_t::value_type);
|
||||
total_size += constraints_size;
|
||||
if (!silent)
|
||||
{
|
||||
llinfos << "\t" << mConstraints.size() << " constraints at " << constraints_size << " bytes" << llendl;
|
||||
llinfos << "Size: " << total_size << " bytes" << llendl;
|
||||
}
|
||||
|
||||
return total_size;
|
||||
}
|
||||
@@ -427,9 +444,8 @@ void LLKeyframeMotion::JointMotion::update(LLJointState* joint_state, F32 time,
|
||||
// LLKeyframeMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLKeyframeMotion::LLKeyframeMotion(const LLUUID &id)
|
||||
: LLMotion(id),
|
||||
mJointMotionList(NULL),
|
||||
LLKeyframeMotion::LLKeyframeMotion(const LLUUID &id, LLMotionController* controller)
|
||||
: LLMotion(id, controller),
|
||||
mPelvisp(NULL),
|
||||
mLastSkeletonSerialNum(0),
|
||||
mLastUpdateTime(0.f),
|
||||
@@ -452,9 +468,9 @@ LLKeyframeMotion::~LLKeyframeMotion()
|
||||
//-----------------------------------------------------------------------------
|
||||
// create()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLMotion *LLKeyframeMotion::create(const LLUUID &id)
|
||||
LLMotion* LLKeyframeMotion::create(LLUUID const& id, LLMotionController* controller)
|
||||
{
|
||||
return new LLKeyframeMotion(id);
|
||||
return new LLKeyframeMotion(id, controller);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -517,6 +533,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
|
||||
case ASSET_FETCHED:
|
||||
return STATUS_HOLD;
|
||||
case ASSET_FETCH_FAILED:
|
||||
llwarns << "Trying to initialize a motion that failed to be fetched." << llendl;
|
||||
return STATUS_FAILURE;
|
||||
case ASSET_LOADED:
|
||||
return STATUS_SUCCESS;
|
||||
@@ -526,7 +543,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
|
||||
break;
|
||||
}
|
||||
|
||||
LLKeyframeMotion::JointMotionList* joint_motion_list = LLKeyframeDataCache::getKeyframeData(getID());
|
||||
LLKeyframeMotion::JointMotionListPtr joint_motion_list = LLKeyframeDataCache::getKeyframeData(getID());
|
||||
|
||||
if(joint_motion_list)
|
||||
{
|
||||
@@ -801,7 +818,44 @@ void LLKeyframeMotion::onDeactivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
// setStopTime()
|
||||
//-----------------------------------------------------------------------------
|
||||
// time is in seconds since character creation
|
||||
//
|
||||
// Consider a looping animation of 20 frames, where the loop in point is at 3 frames
|
||||
// and the loop out point at 16 frames:
|
||||
//
|
||||
// The first 3 frames of the animation would be the "loop in" animation.
|
||||
// The last 4 frames of the animation would be the "loop out" animation.
|
||||
// Frames 4 through 15 would be the looping animation frames.
|
||||
//
|
||||
// If the animation would not be looping, all frames would just be played once sequentially:
|
||||
//
|
||||
// mActivationTimestamp -.
|
||||
// v
|
||||
// 0 3 15 16 20
|
||||
// | | \| |
|
||||
// ---------------------
|
||||
// <--> <-- mLoopInPoint (relative to mActivationTimestamp)
|
||||
// <--------------> <-- mLoopOutPoint (relative to mActivationTimestamp)
|
||||
// <----mDuration------>
|
||||
//
|
||||
// When looping the animation would repeat frames 3 to 16 (loop) a few times, for example:
|
||||
//
|
||||
// 0 3 15 3 15 3 15 3 15 16 20
|
||||
// | | loop 1 \| loop 2 \| loop 3 \| loop 4 \| |
|
||||
// ------------------------------------------------------------
|
||||
//LOOP^ ^ LOOP
|
||||
// IN | <----->| OUT
|
||||
// start_loop_time loop_fraction_time-' time
|
||||
//
|
||||
// The time at which the animation is started corresponds to frame 0 and is stored
|
||||
// in mActivationTimestamp (in seconds since character creation).
|
||||
//
|
||||
// If setStopTime() is called with a time somewhere inside loop 4,
|
||||
// then 'loop_fraction_time' is the time from the beginning of
|
||||
// loop 4 till 'time'. Thus 'time - loop_fraction_time' is the first
|
||||
// frame of loop 4, and '(time - loop_fraction_time) +
|
||||
// (mJointMotionList->mDuration - mJointMotionList->mLoopInPoint)'
|
||||
// would correspond to frame 20.
|
||||
//
|
||||
void LLKeyframeMotion::setStopTime(F32 time)
|
||||
{
|
||||
LLMotion::setStopTime(time);
|
||||
@@ -819,6 +873,8 @@ void LLKeyframeMotion::setStopTime(F32 time)
|
||||
loop_fraction_time = fmod(time - start_loop_time,
|
||||
mJointMotionList->mLoopOutPoint - mJointMotionList->mLoopInPoint);
|
||||
}
|
||||
// This sets mStopTimestamp to the time that corresponds to the end of the animation (ie, frame 20 in the above example)
|
||||
// minus the ease out duration, so that the animation eases out during the loop out and finishes exactly at the end.
|
||||
mStopTimestamp = llmax(time,
|
||||
(time - loop_fraction_time) + (mJointMotionList->mDuration - mJointMotionList->mLoopInPoint) - getEaseOutDuration());
|
||||
}
|
||||
@@ -1227,13 +1283,42 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
|
||||
}
|
||||
}
|
||||
|
||||
// Helper class.
|
||||
template<typename T>
|
||||
struct AIAutoDestruct
|
||||
{
|
||||
T* mPtr;
|
||||
AIAutoDestruct() : mPtr(NULL) { }
|
||||
~AIAutoDestruct() { delete mPtr; }
|
||||
void add(T* ptr) { mPtr = ptr; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// deserialize()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
{
|
||||
BOOL old_version = FALSE;
|
||||
mJointMotionList = new LLKeyframeMotion::JointMotionList;
|
||||
|
||||
//<singu>
|
||||
|
||||
// First add a new LLKeyframeMotion::JointMotionList to the cache, then assign a pointer
|
||||
// to that to mJointMotionList. In LLs code the cache is never deleted again. Now it is
|
||||
// is deleted when the last mJointMotionList pointer is destructed.
|
||||
//
|
||||
// It is possible that we get here for an already added animation, because animations can
|
||||
// be requested multiple times (we get here from LLKeyframeMotion::onLoadComplete) when
|
||||
// the animation was still downloading from a previous request for another LLMotionController
|
||||
// object (avatar). In that case we just overwrite the old data while decoding it again.
|
||||
mJointMotionList = LLKeyframeDataCache::getKeyframeData(getID());
|
||||
bool singu_new_joint_motion_list = !mJointMotionList;
|
||||
if (singu_new_joint_motion_list)
|
||||
{
|
||||
// Create a new JointMotionList.
|
||||
mJointMotionList = LLKeyframeDataCache::createKeyframeData(getID());
|
||||
}
|
||||
|
||||
//</singu>
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// get base priority
|
||||
@@ -1396,8 +1481,10 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mJointMotionList->mJointMotionArray.clear();
|
||||
mJointMotionList->mJointMotionArray.reserve(num_motions);
|
||||
if (singu_new_joint_motion_list)
|
||||
{
|
||||
mJointMotionList->mJointMotionArray.reserve(num_motions);
|
||||
}
|
||||
mJointStates.clear();
|
||||
mJointStates.reserve(num_motions);
|
||||
|
||||
@@ -1407,8 +1494,19 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
|
||||
for(U32 i=0; i<num_motions; ++i)
|
||||
{
|
||||
AIAutoDestruct<JointMotion> watcher;
|
||||
|
||||
JointMotion* joint_motion = new JointMotion;
|
||||
mJointMotionList->mJointMotionArray.push_back(joint_motion);
|
||||
if (singu_new_joint_motion_list)
|
||||
{
|
||||
// Pass ownership to mJointMotionList.
|
||||
mJointMotionList->mJointMotionArray.push_back(joint_motion);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just delete this at the end.
|
||||
watcher.add(joint_motion);
|
||||
}
|
||||
|
||||
std::string joint_name;
|
||||
if (!dp.unpackString(joint_name, "joint_name"))
|
||||
@@ -1836,7 +1934,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mJointMotionList->mConstraints.push_front(constraintp);
|
||||
AIAutoDestruct<JointConstraintSharedData> watcher;
|
||||
if (singu_new_joint_motion_list)
|
||||
{
|
||||
mJointMotionList->mConstraints.push_front(constraintp);
|
||||
}
|
||||
else
|
||||
{
|
||||
watcher.add(constraintp);
|
||||
}
|
||||
|
||||
constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte
|
||||
|
||||
@@ -1876,15 +1982,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
if (constraintp->mJointStateIndices[i] < 0 )
|
||||
{
|
||||
llwarns << "No joint index for constraint " << i << llendl;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *FIX: support cleanup of old keyframe data
|
||||
LLKeyframeDataCache::addKeyframeData(getID(), mJointMotionList);
|
||||
mAssetStatus = ASSET_LOADED;
|
||||
|
||||
setupPose();
|
||||
@@ -2226,16 +2329,24 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
|
||||
//--------------------------------------------------------------------
|
||||
// LLKeyframeDataCache::dumpDiagInfo()
|
||||
//--------------------------------------------------------------------
|
||||
void LLKeyframeDataCache::dumpDiagInfo()
|
||||
// <singu>
|
||||
// quiet = 0 : print everything in detail.
|
||||
// 1 : print the UUIDs of all animations in the cache and the total memory usage.
|
||||
// 2 : only print the total memory usage.
|
||||
// </singu>
|
||||
void LLKeyframeDataCache::dumpDiagInfo(int quiet)
|
||||
{
|
||||
// keep track of totals
|
||||
U32 total_size = 0;
|
||||
|
||||
char buf[1024]; /* Flawfinder: ignore */
|
||||
|
||||
llinfos << "-----------------------------------------------------" << llendl;
|
||||
llinfos << " Global Motion Table (DEBUG only)" << llendl;
|
||||
llinfos << "-----------------------------------------------------" << llendl;
|
||||
if (quiet < 2)
|
||||
{
|
||||
llinfos << "-----------------------------------------------------" << llendl;
|
||||
llinfos << " Global Motion Table" << llendl;
|
||||
llinfos << "-----------------------------------------------------" << llendl;
|
||||
}
|
||||
|
||||
// print each loaded mesh, and it's memory usage
|
||||
for (keyframe_data_map_t::iterator map_it = sKeyframeDataMap.begin();
|
||||
@@ -2243,30 +2354,46 @@ void LLKeyframeDataCache::dumpDiagInfo()
|
||||
{
|
||||
U32 joint_motion_kb;
|
||||
|
||||
LLKeyframeMotion::JointMotionList *motion_list_p = map_it->second;
|
||||
LLKeyframeMotion::JointMotionList const* motion_list_p = map_it->get();
|
||||
|
||||
llinfos << "Motion: " << map_it->first << llendl;
|
||||
if (quiet < 2)
|
||||
{
|
||||
llinfos << "Motion: " << map_it->key() << llendl;
|
||||
}
|
||||
|
||||
joint_motion_kb = motion_list_p->dumpDiagInfo();
|
||||
|
||||
total_size += joint_motion_kb;
|
||||
if (motion_list_p)
|
||||
{
|
||||
joint_motion_kb = motion_list_p->dumpDiagInfo(quiet);
|
||||
total_size += joint_motion_kb;
|
||||
}
|
||||
}
|
||||
|
||||
llinfos << "-----------------------------------------------------" << llendl;
|
||||
if (quiet < 2)
|
||||
{
|
||||
llinfos << "-----------------------------------------------------" << llendl;
|
||||
}
|
||||
llinfos << "Motions\tTotal Size" << llendl;
|
||||
snprintf(buf, sizeof(buf), "%d\t\t%d bytes", (S32)sKeyframeDataMap.size(), total_size ); /* Flawfinder: ignore */
|
||||
llinfos << buf << llendl;
|
||||
llinfos << "-----------------------------------------------------" << llendl;
|
||||
if (quiet < 2)
|
||||
{
|
||||
llinfos << "-----------------------------------------------------" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// LLKeyframeDataCache::addKeyframeData()
|
||||
// LLKeyframeDataCache::createKeyframeData()
|
||||
//--------------------------------------------------------------------
|
||||
void LLKeyframeDataCache::addKeyframeData(const LLUUID& id, LLKeyframeMotion::JointMotionList* joint_motion_listp)
|
||||
//<singu> This function replaces LLKeyframeDataCache::addKeyframeData and was rewritten to fix a memory leak (aka, the usage of AICachedPointer).
|
||||
LLKeyframeMotion::JointMotionListPtr LLKeyframeDataCache::createKeyframeData(LLUUID const& id)
|
||||
{
|
||||
sKeyframeDataMap[id] = joint_motion_listp;
|
||||
std::pair<keyframe_data_map_t::iterator, bool> result =
|
||||
sKeyframeDataMap.insert(AICachedPointer<LLUUID, LLKeyframeMotion::JointMotionList>(id, new LLKeyframeMotion::JointMotionList, &sKeyframeDataMap));
|
||||
llassert(result.second); // id may not already exist in the cache.
|
||||
return &*result.first; // Construct and return a JointMotionListPt from a pointer to the actually inserted AICachedPointer.
|
||||
}
|
||||
//</singu>
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// LLKeyframeDataCache::removeKeyframeData()
|
||||
@@ -2276,7 +2403,6 @@ void LLKeyframeDataCache::removeKeyframeData(const LLUUID& id)
|
||||
keyframe_data_map_t::iterator found_data = sKeyframeDataMap.find(id);
|
||||
if (found_data != sKeyframeDataMap.end())
|
||||
{
|
||||
delete found_data->second;
|
||||
sKeyframeDataMap.erase(found_data);
|
||||
}
|
||||
}
|
||||
@@ -2284,14 +2410,14 @@ void LLKeyframeDataCache::removeKeyframeData(const LLUUID& id)
|
||||
//--------------------------------------------------------------------
|
||||
// LLKeyframeDataCache::getKeyframeData()
|
||||
//--------------------------------------------------------------------
|
||||
LLKeyframeMotion::JointMotionList* LLKeyframeDataCache::getKeyframeData(const LLUUID& id)
|
||||
LLKeyframeMotion::JointMotionListPtr LLKeyframeDataCache::getKeyframeData(const LLUUID& id)
|
||||
{
|
||||
keyframe_data_map_t::iterator found_data = sKeyframeDataMap.find(id);
|
||||
if (found_data == sKeyframeDataMap.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return found_data->second;
|
||||
return &*found_data; // Construct and return a JointMotionListPt from a pointer to the found AICachedPointer.
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
@@ -2307,7 +2433,6 @@ LLKeyframeDataCache::~LLKeyframeDataCache()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLKeyframeDataCache::clear()
|
||||
{
|
||||
for_each(sKeyframeDataMap.begin(), sKeyframeDataMap.end(), DeletePairedPointer());
|
||||
sKeyframeDataMap.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
* AICachedPointer and AICachedPointPtr copyright (c) 2013, Aleric Inglewood.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
@@ -48,10 +49,12 @@
|
||||
#include "v3dmath.h"
|
||||
#include "v3math.h"
|
||||
#include "llbvhconsts.h"
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
class LLKeyframeDataCache;
|
||||
class LLVFS;
|
||||
class LLDataPacker;
|
||||
class LLMotionController;
|
||||
|
||||
#define MIN_REQUIRED_PIXEL_AREA_KEYFRAME (40.f)
|
||||
#define MAX_CHAIN_LENGTH (4)
|
||||
@@ -59,6 +62,112 @@ class LLDataPacker;
|
||||
const S32 KEYFRAME_MOTION_VERSION = 1;
|
||||
const S32 KEYFRAME_MOTION_SUBVERSION = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// <singu>
|
||||
|
||||
template<typename KEY, typename T>
|
||||
class AICachedPointer;
|
||||
|
||||
template<typename KEY, typename T>
|
||||
void intrusive_ptr_add_ref(AICachedPointer<KEY, T> const* p);
|
||||
|
||||
template<typename KEY, typename T>
|
||||
void intrusive_ptr_release(AICachedPointer<KEY, T> const* p);
|
||||
|
||||
template<typename KEY, typename T>
|
||||
class AICachedPointer
|
||||
{
|
||||
public:
|
||||
typedef std::set<AICachedPointer<KEY, T> > container_type;
|
||||
|
||||
private:
|
||||
KEY mKey; // The unique key.
|
||||
LLPointer<T> mData; // The actual data pointer.
|
||||
container_type* mCache; // Pointer to the underlaying cache.
|
||||
mutable int mRefCount; // Number of AICachedPointerPtr's pointing to this object.
|
||||
|
||||
public:
|
||||
// Construct a NULL pointer. This is needed when adding a new entry to a std::set, it is always first default constructed.
|
||||
AICachedPointer(void) : mCache(NULL) { }
|
||||
|
||||
// Copy constructor. This is needed to replace the std::set inserted instance with its actual value.
|
||||
AICachedPointer(AICachedPointer const& cptr) : mKey(cptr.mKey), mData(cptr.mData), mCache(cptr.mCache), mRefCount(0) { }
|
||||
|
||||
// Construct a AICachedPointer that points to 'ptr' with key 'key'.
|
||||
AICachedPointer(KEY const& key, T* ptr, container_type* cache) : mKey(key), mData(ptr), mCache(cache), mRefCount(-1) { }
|
||||
|
||||
// Construct a temporary NULL pointer that can be used in a search for a key.
|
||||
AICachedPointer(KEY const& key) : mKey(key), mCache(NULL) { }
|
||||
|
||||
// Accessors for key and data.
|
||||
KEY const& key(void) const { return mKey; }
|
||||
T const* get(void) const { return mData.get(); }
|
||||
T* get(void) { return mData.get(); }
|
||||
|
||||
// Order only by key.
|
||||
friend bool operator<(AICachedPointer const& cp1, AICachedPointer const& cp2) { return cp1.mKey < cp2.mKey; }
|
||||
|
||||
private:
|
||||
friend void intrusive_ptr_add_ref<>(AICachedPointer<KEY, T> const* p);
|
||||
friend void intrusive_ptr_release<>(AICachedPointer<KEY, T> const* p);
|
||||
|
||||
private:
|
||||
AICachedPointer& operator=(AICachedPointer const&);
|
||||
};
|
||||
|
||||
template<typename KEY, typename T>
|
||||
void intrusive_ptr_add_ref(AICachedPointer<KEY, T> const* p)
|
||||
{
|
||||
llassert(p->mCache);
|
||||
if (p->mCache)
|
||||
{
|
||||
p->mRefCount++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename KEY, typename T>
|
||||
void intrusive_ptr_release(AICachedPointer<KEY, T> const* p)
|
||||
{
|
||||
llassert(p->mCache);
|
||||
if (p->mCache)
|
||||
{
|
||||
if (--p->mRefCount == 0)
|
||||
{
|
||||
p->mCache->erase(p->mKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename KEY, typename T>
|
||||
class AICachedPointerPtr
|
||||
{
|
||||
private:
|
||||
boost::intrusive_ptr<AICachedPointer<KEY, T> const> mPtr;
|
||||
static int sCnt;
|
||||
|
||||
public:
|
||||
AICachedPointerPtr(void) { ++sCnt; }
|
||||
AICachedPointerPtr(AICachedPointerPtr const& cpp) : mPtr(cpp.mPtr) { ++sCnt; }
|
||||
AICachedPointerPtr(AICachedPointer<KEY, T> const* cp) : mPtr(cp) { ++sCnt; }
|
||||
~AICachedPointerPtr() { --sCnt; }
|
||||
|
||||
typedef boost::intrusive_ptr<AICachedPointer<KEY, T> const> const AICachedPointerPtr<KEY, T>::* const bool_type;
|
||||
operator bool_type() const { return mPtr ? &AICachedPointerPtr<KEY, T>::mPtr : NULL; }
|
||||
|
||||
T const* operator->() const { return mPtr->get(); }
|
||||
T* operator->() { return const_cast<AICachedPointer<KEY, T>&>(*mPtr).get(); }
|
||||
T const& operator*() const { return *mPtr->get(); }
|
||||
T& operator*() { return *const_cast<AICachedPointer<KEY, T>&>(*mPtr).get(); }
|
||||
|
||||
AICachedPointerPtr& operator=(AICachedPointerPtr const& cpp) { mPtr = cpp.mPtr; return *this; }
|
||||
};
|
||||
|
||||
template<typename KEY, typename T>
|
||||
int AICachedPointerPtr<KEY, T>::sCnt;
|
||||
|
||||
// </singu>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class LLKeyframeMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -68,7 +177,7 @@ class LLKeyframeMotion :
|
||||
friend class LLKeyframeDataCache;
|
||||
public:
|
||||
// Constructor
|
||||
LLKeyframeMotion(const LLUUID &id);
|
||||
LLKeyframeMotion(const LLUUID &id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLKeyframeMotion();
|
||||
@@ -85,7 +194,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID& id);
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -158,7 +267,7 @@ public:
|
||||
U32 getFileSize();
|
||||
BOOL serialize(LLDataPacker& dp) const;
|
||||
BOOL deserialize(LLDataPacker& dp);
|
||||
BOOL isLoaded() { return mJointMotionList != NULL; }
|
||||
BOOL isLoaded() { return !!mJointMotionList; }
|
||||
|
||||
|
||||
// setters for modifying a keyframe animation
|
||||
@@ -393,7 +502,7 @@ public:
|
||||
//-------------------------------------------------------------------------
|
||||
// JointMotionList
|
||||
//-------------------------------------------------------------------------
|
||||
class JointMotionList
|
||||
class JointMotionList : public LLRefCount
|
||||
{
|
||||
public:
|
||||
std::vector<JointMotion*> mJointMotionArray;
|
||||
@@ -416,19 +525,22 @@ public:
|
||||
public:
|
||||
JointMotionList();
|
||||
~JointMotionList();
|
||||
U32 dumpDiagInfo();
|
||||
U32 dumpDiagInfo(bool silent = false) const;
|
||||
JointMotion* getJointMotion(U32 index) const { llassert(index < mJointMotionArray.size()); return mJointMotionArray[index]; }
|
||||
U32 getNumJointMotions() const { return mJointMotionArray.size(); }
|
||||
};
|
||||
|
||||
|
||||
// Singu: Type of a pointer to the cached pointer (in LLKeyframeDataCache::sKeyframeDataMap) to a JointMotionList object.
|
||||
typedef AICachedPointerPtr<LLUUID, JointMotionList> JointMotionListPtr;
|
||||
|
||||
protected:
|
||||
static LLVFS* sVFS;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Member Data
|
||||
//-------------------------------------------------------------------------
|
||||
JointMotionList* mJointMotionList;
|
||||
JointMotionListPtr mJointMotionList; // singu: automatically clean up cache entry when destructed.
|
||||
std::vector<LLPointer<LLJointState> > mJointStates;
|
||||
LLJoint* mPelvisp;
|
||||
LLCharacter* mCharacter;
|
||||
@@ -442,21 +554,24 @@ protected:
|
||||
|
||||
class LLKeyframeDataCache
|
||||
{
|
||||
public:
|
||||
// *FIX: implement this as an actual singleton member of LLKeyframeMotion
|
||||
private:
|
||||
friend class LLKeyframeMotion;
|
||||
LLKeyframeDataCache(){};
|
||||
~LLKeyframeDataCache();
|
||||
|
||||
typedef std::map<LLUUID, class LLKeyframeMotion::JointMotionList*> keyframe_data_map_t;
|
||||
public:
|
||||
typedef AICachedPointer<LLUUID, LLKeyframeMotion::JointMotionList>::container_type keyframe_data_map_t; // singu: add automatic cache cleanup.
|
||||
static keyframe_data_map_t sKeyframeDataMap;
|
||||
|
||||
static void addKeyframeData(const LLUUID& id, LLKeyframeMotion::JointMotionList*);
|
||||
static LLKeyframeMotion::JointMotionList* getKeyframeData(const LLUUID& id);
|
||||
//<singu>
|
||||
static LLKeyframeMotion::JointMotionListPtr createKeyframeData(LLUUID const& id); // id may not exist.
|
||||
static LLKeyframeMotion::JointMotionListPtr getKeyframeData(LLUUID const& id); // id may or may not exists. Returns a NULL pointer when it doesn't exist.
|
||||
//</singu>
|
||||
|
||||
static void removeKeyframeData(const LLUUID& id);
|
||||
|
||||
//print out diagnostic info
|
||||
static void dumpDiagInfo();
|
||||
static void dumpDiagInfo(int quiet = 0); // singu: added param 'quiet'.
|
||||
static void clear();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,456 +0,0 @@
|
||||
/**
|
||||
* @file llkeyframemotionparam.cpp
|
||||
* @brief Implementation of LLKeyframeMotion class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Header Files
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llkeyframemotionparam.h"
|
||||
#include "llcharacter.h"
|
||||
#include "llmath.h"
|
||||
#include "m3math.h"
|
||||
#include "lldir.h"
|
||||
#include "llanimationstates.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLKeyframeMotionParam class
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLKeyframeMotionParam()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLKeyframeMotionParam::LLKeyframeMotionParam( const LLUUID &id) : LLMotion(id)
|
||||
{
|
||||
mDefaultKeyframeMotion = NULL;
|
||||
mCharacter = NULL;
|
||||
|
||||
mEaseInDuration = 0.f;
|
||||
mEaseOutDuration = 0.f;
|
||||
mDuration = 0.f;
|
||||
mPriority = LLJoint::LOW_PRIORITY;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ~LLKeyframeMotionParam()
|
||||
// Class Destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLKeyframeMotionParam::~LLKeyframeMotionParam()
|
||||
{
|
||||
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
|
||||
iter != mParameterizedMotions.end(); ++iter)
|
||||
{
|
||||
motion_list_t& motionList = iter->second;
|
||||
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
|
||||
{
|
||||
const ParameterizedMotion& paramMotion = *iter2;
|
||||
delete paramMotion.mMotion;
|
||||
}
|
||||
motionList.clear();
|
||||
}
|
||||
mParameterizedMotions.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLKeyframeMotionParam::onInitialize(LLCharacter *character)
|
||||
//-----------------------------------------------------------------------------
|
||||
LLMotion::LLMotionInitStatus LLKeyframeMotionParam::onInitialize(LLCharacter *character)
|
||||
{
|
||||
mCharacter = character;
|
||||
|
||||
if (!loadMotions())
|
||||
{
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
|
||||
iter != mParameterizedMotions.end(); ++iter)
|
||||
{
|
||||
motion_list_t& motionList = iter->second;
|
||||
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
|
||||
{
|
||||
const ParameterizedMotion& paramMotion = *iter2;
|
||||
LLMotion* motion = paramMotion.mMotion;
|
||||
motion->onInitialize(character);
|
||||
|
||||
if (motion->getDuration() > mEaseInDuration)
|
||||
{
|
||||
mEaseInDuration = motion->getEaseInDuration();
|
||||
}
|
||||
|
||||
if (motion->getEaseOutDuration() > mEaseOutDuration)
|
||||
{
|
||||
mEaseOutDuration = motion->getEaseOutDuration();
|
||||
}
|
||||
|
||||
if (motion->getDuration() > mDuration)
|
||||
{
|
||||
mDuration = motion->getDuration();
|
||||
}
|
||||
|
||||
if (motion->getPriority() > mPriority)
|
||||
{
|
||||
mPriority = motion->getPriority();
|
||||
}
|
||||
|
||||
LLPose *pose = motion->getPose();
|
||||
|
||||
mPoseBlender.addMotion(motion);
|
||||
for (LLJointState *jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState())
|
||||
{
|
||||
LLPose *blendedPose = mPoseBlender.getBlendedPose();
|
||||
blendedPose->addJointState(jsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLKeyframeMotionParam::onActivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLKeyframeMotionParam::onActivate()
|
||||
{
|
||||
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
|
||||
iter != mParameterizedMotions.end(); ++iter)
|
||||
{
|
||||
motion_list_t& motionList = iter->second;
|
||||
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
|
||||
{
|
||||
const ParameterizedMotion& paramMotion = *iter2;
|
||||
paramMotion.mMotion->activate(mActivationTimestamp);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLKeyframeMotionParam::onUpdate()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask)
|
||||
{
|
||||
F32 weightFactor = 1.f / (F32)mParameterizedMotions.size();
|
||||
|
||||
// zero out all pose weights
|
||||
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
|
||||
iter != mParameterizedMotions.end(); ++iter)
|
||||
{
|
||||
motion_list_t& motionList = iter->second;
|
||||
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
|
||||
{
|
||||
const ParameterizedMotion& paramMotion = *iter2;
|
||||
// llinfos << "Weight for pose " << paramMotion.mMotion->getName() << " is " << paramMotion.mMotion->getPose()->getWeight() << llendl;
|
||||
paramMotion.mMotion->getPose()->setWeight(0.f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
|
||||
iter != mParameterizedMotions.end(); ++iter)
|
||||
{
|
||||
const std::string& paramName = iter->first;
|
||||
F32* paramValue = (F32 *)mCharacter->getAnimationData(paramName);
|
||||
if (NULL == paramValue) // unexpected, but...
|
||||
{
|
||||
llwarns << "paramValue == NULL" << llendl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// DANGER! Do not modify mParameterizedMotions while using these pointers!
|
||||
const ParameterizedMotion* firstMotion = NULL;
|
||||
const ParameterizedMotion* secondMotion = NULL;
|
||||
|
||||
motion_list_t& motionList = iter->second;
|
||||
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
|
||||
{
|
||||
const ParameterizedMotion& paramMotion = *iter2;
|
||||
paramMotion.mMotion->onUpdate(time, joint_mask);
|
||||
|
||||
F32 distToParam = paramMotion.mParam - *paramValue;
|
||||
|
||||
if ( distToParam <= 0.f)
|
||||
{
|
||||
// keep track of the motion closest to the parameter value
|
||||
firstMotion = ¶mMotion;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we've passed the parameter value
|
||||
// so store the first motion we find as the second one we want to blend...
|
||||
if (firstMotion && !secondMotion )
|
||||
{
|
||||
secondMotion = ¶mMotion;
|
||||
}
|
||||
//...or, if we've seen no other motion so far, make sure we blend to this only
|
||||
else if (!firstMotion)
|
||||
{
|
||||
firstMotion = ¶mMotion;
|
||||
secondMotion = ¶mMotion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLPose *firstPose;
|
||||
LLPose *secondPose;
|
||||
|
||||
if (firstMotion)
|
||||
firstPose = firstMotion->mMotion->getPose();
|
||||
else
|
||||
firstPose = NULL;
|
||||
|
||||
if (secondMotion)
|
||||
secondPose = secondMotion->mMotion->getPose();
|
||||
else
|
||||
secondPose = NULL;
|
||||
|
||||
// now modify weight of the subanim (only if we are blending between two motions)
|
||||
if (firstMotion && secondMotion)
|
||||
{
|
||||
if (firstMotion == secondMotion)
|
||||
{
|
||||
firstPose->setWeight(weightFactor);
|
||||
}
|
||||
else if (firstMotion->mParam == secondMotion->mParam)
|
||||
{
|
||||
firstPose->setWeight(0.5f * weightFactor);
|
||||
secondPose->setWeight(0.5f * weightFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 first_weight = 1.f -
|
||||
((llclamp(*paramValue - firstMotion->mParam, 0.f, (secondMotion->mParam - firstMotion->mParam))) /
|
||||
(secondMotion->mParam - firstMotion->mParam));
|
||||
first_weight = llclamp(first_weight, 0.f, 1.f);
|
||||
|
||||
F32 second_weight = 1.f - first_weight;
|
||||
|
||||
firstPose->setWeight(first_weight * weightFactor);
|
||||
secondPose->setWeight(second_weight * weightFactor);
|
||||
|
||||
// llinfos << "Parameter " << *paramName << ": " << *paramValue << llendl;
|
||||
// llinfos << "Weights " << firstPose->getWeight() << " " << secondPose->getWeight() << llendl;
|
||||
}
|
||||
}
|
||||
else if (firstMotion && !secondMotion)
|
||||
{
|
||||
firstPose->setWeight(weightFactor);
|
||||
}
|
||||
}
|
||||
|
||||
// blend poses
|
||||
mPoseBlender.blendAndApply();
|
||||
|
||||
llinfos << "Param Motion weight " << mPoseBlender.getBlendedPose()->getWeight() << llendl;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLKeyframeMotionParam::onDeactivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLKeyframeMotionParam::onDeactivate()
|
||||
{
|
||||
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
|
||||
iter != mParameterizedMotions.end(); ++iter)
|
||||
{
|
||||
motion_list_t& motionList = iter->second;
|
||||
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
|
||||
{
|
||||
const ParameterizedMotion& paramMotion = *iter2;
|
||||
paramMotion.mMotion->onDeactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLKeyframeMotionParam::addKeyframeMotion()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLKeyframeMotionParam::addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value)
|
||||
{
|
||||
LLMotion *newMotion = mCharacter->createMotion( id );
|
||||
|
||||
if (!newMotion)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
newMotion->setName(name);
|
||||
|
||||
// now add motion to this list
|
||||
mParameterizedMotions[param].insert(ParameterizedMotion(newMotion, value));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLKeyframeMotionParam::setDefaultKeyframeMotion()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLKeyframeMotionParam::setDefaultKeyframeMotion(char *name)
|
||||
{
|
||||
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
|
||||
iter != mParameterizedMotions.end(); ++iter)
|
||||
{
|
||||
motion_list_t& motionList = iter->second;
|
||||
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
|
||||
{
|
||||
const ParameterizedMotion& paramMotion = *iter2;
|
||||
if (paramMotion.mMotion->getName() == name)
|
||||
{
|
||||
mDefaultKeyframeMotion = paramMotion.mMotion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// loadMotions()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLKeyframeMotionParam::loadMotions()
|
||||
{
|
||||
//-------------------------------------------------------------------------
|
||||
// Load named file by concatenating the character prefix with the motion name.
|
||||
// Load data into a buffer to be parsed.
|
||||
//-------------------------------------------------------------------------
|
||||
//std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix())
|
||||
// + "_" + getName() + ".llp";
|
||||
//RN: deprecated unused reference to "motion" directory
|
||||
std::string path;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// open the file
|
||||
//-------------------------------------------------------------------------
|
||||
S32 fileSize = 0;
|
||||
LLAPRFile infile(path, LL_APR_R, &fileSize);
|
||||
apr_file_t* fp = infile.getFileHandle() ;
|
||||
if (!fp || fileSize == 0)
|
||||
{
|
||||
llinfos << "ERROR: can't open: " << path << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// allocate a text buffer
|
||||
try
|
||||
{
|
||||
std::vector<char> text(fileSize+1);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// load data from file into buffer
|
||||
//-------------------------------------------------------------------------
|
||||
bool error = false;
|
||||
char *p = &text[0];
|
||||
while ( 1 )
|
||||
{
|
||||
if (apr_file_eof(fp) == APR_EOF)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (apr_file_gets(p, 1024, fp) != APR_SUCCESS)
|
||||
{
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
while ( *(++p) )
|
||||
;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// close the file
|
||||
//-------------------------------------------------------------------------
|
||||
infile.close();
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// check for error
|
||||
//-------------------------------------------------------------------------
|
||||
llassert( p <= (&text[0] + fileSize) );
|
||||
|
||||
if ( error )
|
||||
{
|
||||
llinfos << "ERROR: error while reading from " << path << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
llinfos << "Loading parametric keyframe data for: " << getName() << llendl;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// parse the text and build keyframe data structures
|
||||
//-------------------------------------------------------------------------
|
||||
p = &text[0];
|
||||
S32 num;
|
||||
char strA[80]; /* Flawfinder: ignore */
|
||||
char strB[80]; /* Flawfinder: ignore */
|
||||
F32 floatA = 0.0f;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// get priority
|
||||
//-------------------------------------------------------------------------
|
||||
BOOL isFirstMotion = TRUE;
|
||||
num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (num == 0 || num == EOF) break;
|
||||
if ((num != 3))
|
||||
{
|
||||
llinfos << "WARNING: can't read parametric motion" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
addKeyframeMotion(strA, gAnimLibrary.stringToAnimState(std::string(strA)), strB, floatA);
|
||||
if (isFirstMotion)
|
||||
{
|
||||
isFirstMotion = FALSE;
|
||||
setDefaultKeyframeMotion(strA);
|
||||
}
|
||||
|
||||
p = strstr(p, "\n");
|
||||
if (!p)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
p++;
|
||||
num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
catch(std::bad_alloc)
|
||||
{
|
||||
llinfos << "ERROR: Unable to allocate keyframe text buffer." << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// End
|
||||
@@ -1,176 +0,0 @@
|
||||
/**
|
||||
* @file llkeyframemotionparam.h
|
||||
* @brief Implementation of LLKeframeMotionParam class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2002-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLKEYFRAMEMOTIONPARAM_H
|
||||
#define LL_LLKEYFRAMEMOTIONPARAM_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Header files
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "llmotion.h"
|
||||
#include "lljointstate.h"
|
||||
#include "v3math.h"
|
||||
#include "llquaternion.h"
|
||||
#include "linked_lists.h"
|
||||
#include "llkeyframemotion.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class LLKeyframeMotionParam
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLKeyframeMotionParam :
|
||||
public LLMotion
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLKeyframeMotionParam(const LLUUID &id);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLKeyframeMotionParam();
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// functions to support MotionController and MotionRegistry
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLKeyframeMotionParam(id); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// animation callbacks to be implemented by subclasses
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// motions must specify whether or not they loop
|
||||
virtual BOOL getLoop() {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// motions must report their total duration
|
||||
virtual F32 getDuration() {
|
||||
return mDuration;
|
||||
}
|
||||
|
||||
// motions must report their "ease in" duration
|
||||
virtual F32 getEaseInDuration() {
|
||||
return mEaseInDuration;
|
||||
}
|
||||
|
||||
// motions must report their "ease out" duration.
|
||||
virtual F32 getEaseOutDuration() {
|
||||
return mEaseOutDuration;
|
||||
}
|
||||
|
||||
// motions must report their priority
|
||||
virtual LLJoint::JointPriority getPriority() {
|
||||
return mPriority;
|
||||
}
|
||||
|
||||
virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; }
|
||||
|
||||
// called to determine when a motion should be activated/deactivated based on avatar pixel coverage
|
||||
virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_KEYFRAME; }
|
||||
|
||||
// run-time (post constructor) initialization,
|
||||
// called after parameters have been set
|
||||
// must return true to indicate success and be available for activation
|
||||
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
|
||||
|
||||
// called when a motion is activated
|
||||
// must return TRUE to indicate success, or else
|
||||
// it will be deactivated
|
||||
virtual BOOL onActivate();
|
||||
|
||||
// called per time step
|
||||
// must return TRUE while it is active, and
|
||||
// must return FALSE when the motion is completed.
|
||||
virtual BOOL onUpdate(F32 time, U8* joint_mask);
|
||||
|
||||
// called when a motion is deactivated
|
||||
virtual void onDeactivate();
|
||||
|
||||
virtual LLPose* getPose() { return mPoseBlender.getBlendedPose();}
|
||||
|
||||
protected:
|
||||
//-------------------------------------------------------------------------
|
||||
// new functions defined by this subclass
|
||||
//-------------------------------------------------------------------------
|
||||
struct ParameterizedMotion
|
||||
{
|
||||
ParameterizedMotion(LLMotion* motion, F32 param) : mMotion(motion), mParam(param) {}
|
||||
LLMotion* mMotion;
|
||||
F32 mParam;
|
||||
};
|
||||
|
||||
// add a motion and associated parameter triplet
|
||||
BOOL addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value);
|
||||
|
||||
// set default motion for LOD and retrieving blend constants
|
||||
void setDefaultKeyframeMotion(char *);
|
||||
|
||||
BOOL loadMotions();
|
||||
|
||||
protected:
|
||||
//-------------------------------------------------------------------------
|
||||
// Member Data
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
struct compare_motions
|
||||
{
|
||||
bool operator() (const ParameterizedMotion& a, const ParameterizedMotion& b) const
|
||||
{
|
||||
if (a.mParam != b.mParam)
|
||||
return (a.mParam < b.mParam);
|
||||
else
|
||||
return a.mMotion < b.mMotion;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::set < ParameterizedMotion, compare_motions > motion_list_t;
|
||||
typedef std::map <std::string, motion_list_t > motion_map_t;
|
||||
motion_map_t mParameterizedMotions;
|
||||
LLMotion* mDefaultKeyframeMotion;
|
||||
LLCharacter* mCharacter;
|
||||
LLPoseBlender mPoseBlender;
|
||||
|
||||
F32 mEaseInDuration;
|
||||
F32 mEaseOutDuration;
|
||||
F32 mDuration;
|
||||
LLJoint::JointPriority mPriority;
|
||||
|
||||
LLUUID mTransactionID;
|
||||
};
|
||||
|
||||
#endif // LL_LLKEYFRAMEMOTIONPARAM_H
|
||||
@@ -50,7 +50,7 @@ const F32 POSITION_THRESHOLD = 0.1f;
|
||||
// LLKeyframeStandMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLKeyframeStandMotion::LLKeyframeStandMotion(const LLUUID &id) : LLKeyframeMotion(id)
|
||||
LLKeyframeStandMotion::LLKeyframeStandMotion(LLUUID const& id, LLMotionController* controller) : LLKeyframeMotion(id, controller)
|
||||
{
|
||||
mFlipFeet = FALSE;
|
||||
mCharacter = NULL;
|
||||
@@ -286,40 +286,38 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
//-------------------------------------------------------------------------
|
||||
if ( mTrackAnkles )
|
||||
{
|
||||
LLVector4 dirLeft4 = mAnkleLeftJoint.getWorldMatrix().getFwdRow4();
|
||||
LLVector4 dirRight4 = mAnkleRightJoint.getWorldMatrix().getFwdRow4();
|
||||
LLVector3 dirLeft = vec4to3( dirLeft4 );
|
||||
LLVector3 dirRight = vec4to3( dirRight4 );
|
||||
const LLVector4a& dirLeft4 = mAnkleLeftJoint.getWorldMatrix().getRow<LLMatrix4a::ROW_FWD>();
|
||||
const LLVector4a& dirRight4 = mAnkleRightJoint.getWorldMatrix().getRow<LLMatrix4a::ROW_FWD>();
|
||||
|
||||
LLVector3 up;
|
||||
LLVector3 dir;
|
||||
LLVector3 left;
|
||||
LLVector4a up;
|
||||
LLVector4a dir;
|
||||
LLVector4a left;
|
||||
|
||||
up = mNormalLeft;
|
||||
up.normVec();
|
||||
up.load3(mNormalLeft.mV);
|
||||
up.normalize3fast();
|
||||
if (mFlipFeet)
|
||||
{
|
||||
up *= -1.0f;
|
||||
up.negate();
|
||||
}
|
||||
dir = dirLeft;
|
||||
dir.normVec();
|
||||
left = up % dir;
|
||||
left.normVec();
|
||||
dir = left % up;
|
||||
mRotationLeft = LLQuaternion( dir, left, up );
|
||||
dir = dirLeft4;
|
||||
dir.normalize3fast();
|
||||
left.setCross3(up,dir);
|
||||
left.normalize3fast();
|
||||
dir.setCross3(left,up);
|
||||
mRotationLeft = LLQuaternion( LLVector3(dir.getF32ptr()), LLVector3(left.getF32ptr()), LLVector3(up.getF32ptr()));
|
||||
|
||||
up = mNormalRight;
|
||||
up.normVec();
|
||||
up.load3(mNormalRight.mV);
|
||||
up.normalize3fast();
|
||||
if (mFlipFeet)
|
||||
{
|
||||
up *= -1.0f;
|
||||
up.negate();
|
||||
}
|
||||
dir = dirRight;
|
||||
dir.normVec();
|
||||
left = up % dir;
|
||||
left.normVec();
|
||||
dir = left % up;
|
||||
mRotationRight = LLQuaternion( dir, left, up );
|
||||
dir = dirRight4;
|
||||
dir.normalize3fast();
|
||||
left.setCross3(up,dir);
|
||||
left.normalize3fast();
|
||||
dir.setCross3(left,up);
|
||||
mRotationRight = LLQuaternion( LLVector3(dir.getF32ptr()), LLVector3(left.getF32ptr()), LLVector3(up.getF32ptr()));
|
||||
}
|
||||
mAnkleLeftJoint.setWorldRotation( mRotationLeft );
|
||||
mAnkleRightJoint.setWorldRotation( mRotationRight );
|
||||
|
||||
@@ -48,7 +48,7 @@ class LLKeyframeStandMotion :
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLKeyframeStandMotion(const LLUUID &id);
|
||||
LLKeyframeStandMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLKeyframeStandMotion();
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLKeyframeStandMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLKeyframeStandMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@@ -55,8 +55,8 @@ const F32 SPEED_ADJUST_TIME_CONSTANT = 0.1f; // time constant for speed adjustm
|
||||
// LLKeyframeWalkMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLKeyframeWalkMotion::LLKeyframeWalkMotion(const LLUUID &id)
|
||||
: LLKeyframeMotion(id),
|
||||
LLKeyframeWalkMotion::LLKeyframeWalkMotion(LLUUID const& id, LLMotionController* controller)
|
||||
: LLKeyframeMotion(id, controller),
|
||||
mCharacter(NULL),
|
||||
mCyclePhase(0.0f),
|
||||
mRealTimeLast(0.0f),
|
||||
@@ -138,8 +138,8 @@ BOOL LLKeyframeWalkMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
// LLWalkAdjustMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLWalkAdjustMotion::LLWalkAdjustMotion(const LLUUID &id) :
|
||||
LLMotion(id),
|
||||
LLWalkAdjustMotion::LLWalkAdjustMotion(LLUUID const& id, LLMotionController* controller) :
|
||||
AIMaskedMotion(id, controller, ANIM_AGENT_WALK_ADJUST),
|
||||
mLastTime(0.f),
|
||||
mAnimSpeed(0.f),
|
||||
mAdjustedSpeed(0.f),
|
||||
@@ -193,7 +193,7 @@ BOOL LLWalkAdjustMotion::onActivate()
|
||||
F32 rightAnkleOffset = (mRightAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec();
|
||||
mAnkleOffset = llmax(leftAnkleOffset, rightAnkleOffset);
|
||||
|
||||
return TRUE;
|
||||
return AIMaskedMotion::onActivate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -325,13 +325,14 @@ BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
void LLWalkAdjustMotion::onDeactivate()
|
||||
{
|
||||
mCharacter->removeAnimationData("Walk Speed");
|
||||
AIMaskedMotion::onDeactivate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLFlyAdjustMotion::LLFlyAdjustMotion()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLFlyAdjustMotion::LLFlyAdjustMotion(const LLUUID &id)
|
||||
: LLMotion(id),
|
||||
LLFlyAdjustMotion::LLFlyAdjustMotion(LLUUID const& id, LLMotionController* controller)
|
||||
: AIMaskedMotion(id, controller, ANIM_AGENT_FLY_ADJUST),
|
||||
mRoll(0.f)
|
||||
{
|
||||
mName = "fly_adjust";
|
||||
@@ -368,7 +369,7 @@ BOOL LLFlyAdjustMotion::onActivate()
|
||||
mPelvisState->setPosition(LLVector3::zero);
|
||||
mPelvisState->setRotation(LLQuaternion::DEFAULT);
|
||||
mRoll = 0.f;
|
||||
return TRUE;
|
||||
return AIMaskedMotion::onActivate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -52,7 +52,7 @@ class LLKeyframeWalkMotion :
|
||||
friend class LLWalkAdjustMotion;
|
||||
public:
|
||||
// Constructor
|
||||
LLKeyframeWalkMotion(const LLUUID &id);
|
||||
LLKeyframeWalkMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLKeyframeWalkMotion();
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLKeyframeWalkMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLKeyframeWalkMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -86,11 +86,11 @@ public:
|
||||
S32 mDownFoot;
|
||||
};
|
||||
|
||||
class LLWalkAdjustMotion : public LLMotion
|
||||
class LLWalkAdjustMotion : public AIMaskedMotion
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLWalkAdjustMotion(const LLUUID &id);
|
||||
LLWalkAdjustMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLWalkAdjustMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLWalkAdjustMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -136,11 +136,11 @@ public:
|
||||
F32 mAnkleOffset;
|
||||
};
|
||||
|
||||
class LLFlyAdjustMotion : public LLMotion
|
||||
class LLFlyAdjustMotion : public AIMaskedMotion
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLFlyAdjustMotion(const LLUUID &id);
|
||||
LLFlyAdjustMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLFlyAdjustMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLFlyAdjustMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -157,7 +157,6 @@ public:
|
||||
//-------------------------------------------------------------------------
|
||||
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
|
||||
virtual BOOL onActivate();
|
||||
virtual void onDeactivate() {};
|
||||
virtual BOOL onUpdate(F32 time, U8* joint_mask);
|
||||
virtual LLJoint::JointPriority getPriority(){return LLJoint::HIGHER_PRIORITY;}
|
||||
virtual BOOL getLoop() { return TRUE; }
|
||||
|
||||
@@ -37,6 +37,125 @@
|
||||
|
||||
#include "llmotion.h"
|
||||
#include "llcriticaldamp.h"
|
||||
#include "llmotioncontroller.h"
|
||||
|
||||
//<singu>
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// AISyncClientMotion class
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
AISyncKey* AISyncClientMotion::createSyncKey(AISyncKey const* from_key) const
|
||||
{
|
||||
// The const cast is needed because getDuration() is non-const while it should have been.
|
||||
AISyncClientMotion* self = const_cast<AISyncClientMotion*>(this);
|
||||
// Only synchronize motions with the same duration and loop value.
|
||||
return new AISyncKeyMotion(from_key, self->getDuration(), self->getLoop());
|
||||
}
|
||||
|
||||
void AISyncClientMotion::aisync_loading(void)
|
||||
{
|
||||
// Register the motion for (possible) synchronization: this marks the time at which is should have started.
|
||||
unregister_client(); // In case it is already registered. Getting here means we are being (re)started now, we need to synchronize with other motions that start now.
|
||||
register_client();
|
||||
}
|
||||
|
||||
void AISyncClientMotion::aisync_loaded(void)
|
||||
{
|
||||
AISyncServer* server = this->server();
|
||||
if (!server)
|
||||
{
|
||||
// Already expired without being synchronized (no other motion was started at the same time).
|
||||
return;
|
||||
}
|
||||
AISyncKey const& key = server->key(); // The allocation of this is owned by server.
|
||||
// There is no need to resync if there was not another motion started at the same time and the key already expired.
|
||||
bool need_resync = !(server->never_synced() && key.expired());
|
||||
AISyncKey* new_key = NULL;
|
||||
if (need_resync)
|
||||
{
|
||||
// Create a new key using the old start time.
|
||||
new_key = createSyncKey(&key);
|
||||
}
|
||||
server->remove(this); // This resets mServer and might even delete server.
|
||||
if (need_resync)
|
||||
{
|
||||
// Add the client to another server (based on the new key). This takes ownership of the key allocation.
|
||||
AISyncServerMap::instance().register_client(this, new_key);
|
||||
}
|
||||
}
|
||||
|
||||
F32 LLMotion::getRuntime(void) const
|
||||
{
|
||||
llassert(mActive);
|
||||
return mController->getAnimTime() - mActivationTimestamp;
|
||||
}
|
||||
|
||||
F32 LLMotion::getAnimTime(void) const
|
||||
{
|
||||
return mController->getAnimTime();
|
||||
}
|
||||
|
||||
F32 LLMotion::syncActivationTime(F32 time)
|
||||
{
|
||||
AISyncServer* server = this->server();
|
||||
if (!server)
|
||||
{
|
||||
register_client();
|
||||
server = this->server();
|
||||
}
|
||||
AISyncServer::client_list_t const& clients = server->getClients();
|
||||
if (clients.size() > 1)
|
||||
{
|
||||
// Look for the client with the smallest runtime.
|
||||
AISyncClientMotion* motion_with_smallest_runtime = NULL;
|
||||
F32 runtime = 1e10;
|
||||
// Run over all motions in this to be synchronized group.
|
||||
for (AISyncServer::client_list_t::const_iterator client = clients.begin(); client != clients.end(); ++client)
|
||||
{
|
||||
if ((client->mReadyEvents & 2)) // Is this motion active? Motions that aren't loaded yet are not active.
|
||||
{
|
||||
// Currently, if event 2 is set then this is an LLMotion.
|
||||
llassert(dynamic_cast<AISyncClientMotion*>(client->mClientPtr));
|
||||
AISyncClientMotion* motion = static_cast<AISyncClientMotion*>(client->mClientPtr);
|
||||
// Deactivated motions should have been deregistered, certainly not have event 2 set.
|
||||
llassert(static_cast<LLMotion*>(motion)->isActive());
|
||||
if (motion->getRuntime() < runtime)
|
||||
{
|
||||
// This is a bit fuzzy since theoretically the runtime of all active motions in the list should be the same.
|
||||
// Just use the smallest value to get rid of some randomness. We might even synchronizing with ourselves
|
||||
// in which case 'time' would be set to a value such that mActivationTimestamp won't change.
|
||||
// In practise however, this list will contain only two clients: this, being inactive, and our partner.
|
||||
runtime = motion->getRuntime();
|
||||
motion_with_smallest_runtime = motion;
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------
|
||||
// Here is where the actual synchronization takes place.
|
||||
// Current we only synchronize looped motions.
|
||||
if (getLoop())
|
||||
{
|
||||
if (motion_with_smallest_runtime)
|
||||
{
|
||||
// Pretend the motion was started in the past at the same time as the other motion(s).
|
||||
time = getAnimTime() - runtime;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
void AISyncClientMotion::deregistered(void)
|
||||
{
|
||||
#ifdef SHOW_ASSERT
|
||||
mReadyEvents = 0;
|
||||
#endif
|
||||
}
|
||||
//</singu>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -48,10 +167,11 @@
|
||||
// LLMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLMotion::LLMotion( const LLUUID &id ) :
|
||||
LLMotion::LLMotion(LLUUID const& id, LLMotionController* controller) :
|
||||
mStopped(TRUE),
|
||||
mActive(FALSE),
|
||||
mID(id),
|
||||
mController(controller),
|
||||
mActivationTimestamp(0.f),
|
||||
mStopTimestamp(0.f),
|
||||
mSendStopTimestamp(F32_MAX),
|
||||
@@ -147,6 +267,19 @@ void LLMotion::activate(F32 time)
|
||||
{
|
||||
mActivationTimestamp = time;
|
||||
mStopped = FALSE;
|
||||
//<singu>
|
||||
if (mController && !mController->syncing_disabled()) // Avoid being registered when syncing is disabled for this motion.
|
||||
{
|
||||
if (mActive)
|
||||
{
|
||||
// If the motion is already active then we are being restarted.
|
||||
// Unregister it first (if it is registered) so that the call to ready will cause it to be registered
|
||||
// and be synchronized with other motions that are started at this moment.
|
||||
unregister_client();
|
||||
}
|
||||
ready(6, 2 | (mController->isHidden() ? 0 : 4)); // Signal that mActivationTimestamp is set/valid (2), and that this server has a visible motion (4) (or not).
|
||||
}
|
||||
//</singu>
|
||||
mActive = TRUE;
|
||||
onActivate();
|
||||
}
|
||||
@@ -159,6 +292,14 @@ void LLMotion::deactivate()
|
||||
mActive = FALSE;
|
||||
mPose.setWeight(0.f);
|
||||
|
||||
//<singu>
|
||||
if (server()) // Only when this motion is already registered.
|
||||
{
|
||||
ready(6, 0); // Signal that mActivationTimestamp is no longer valid.
|
||||
unregister_client(); // No longer running, so no longer a part of this sync group.
|
||||
}
|
||||
//</singu>
|
||||
|
||||
if (mDeactivateCallback)
|
||||
{
|
||||
(*mDeactivateCallback)(mDeactivateCallbackUserData);
|
||||
@@ -174,4 +315,19 @@ BOOL LLMotion::canDeprecate()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AIMaskedMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
BOOL AIMaskedMotion::onActivate()
|
||||
{
|
||||
mController->activated(mMaskBit);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void AIMaskedMotion::onDeactivate()
|
||||
{
|
||||
mController->deactivated(mMaskBit);
|
||||
}
|
||||
|
||||
// End
|
||||
|
||||
@@ -38,16 +38,85 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <string>
|
||||
|
||||
#include "aisyncclient.h"
|
||||
#include "llerror.h"
|
||||
#include "llpose.h"
|
||||
#include "lluuid.h"
|
||||
|
||||
class LLCharacter;
|
||||
class LLMotionController;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class AISync* stuff
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class AISyncKeyMotion : public AISyncKey
|
||||
{
|
||||
private:
|
||||
F32 mDuration;
|
||||
bool mLoop;
|
||||
|
||||
public:
|
||||
AISyncKeyMotion(AISyncKey const* from_key, F32 duration, bool loop) : AISyncKey(from_key), mDuration(duration), mLoop(loop) { }
|
||||
|
||||
// Virtual functions of AISyncKey.
|
||||
public:
|
||||
/*virtual*/ synckeytype_t getkeytype(void) const
|
||||
{
|
||||
// Return a unique identifier for this class, where the low 8 bits represent the syncgroup.
|
||||
return synckeytype_motion;
|
||||
}
|
||||
|
||||
/*virtual*/ bool equals(AISyncKey const& key) const
|
||||
{
|
||||
switch (key.getkeytype())
|
||||
{
|
||||
case synckeytype_motion:
|
||||
{
|
||||
// The other key is of the same type.
|
||||
AISyncKeyMotion const& motion_key = static_cast<AISyncKeyMotion const&>(key);
|
||||
return mLoop == motion_key.mLoop && is_approx_equal(mDuration, motion_key.mDuration);
|
||||
}
|
||||
default:
|
||||
// The keys must be in the same syncgroup.
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class AISyncClientMotion : public AISyncClient
|
||||
{
|
||||
protected:
|
||||
// Make sure that clients that are destroyed are first unregistered.
|
||||
// This is needed, for example, when loading fails or when excess motions are being purged.
|
||||
/*virtual*/ ~AISyncClientMotion() { unregister_client(); }
|
||||
|
||||
// AISyncClient events.
|
||||
/*virtual*/ AISyncKey* createSyncKey(AISyncKey const* from_key = NULL) const;
|
||||
/*virtual*/ void event1_ready(void) { }
|
||||
/*virtual*/ void event1_not_ready(void) { }
|
||||
/*virtual*/ void deregistered(void);
|
||||
|
||||
protected:
|
||||
// This is called when the server sent us a message that it wants us to play this animation, but we can't because it isn't fully downloaded yet.
|
||||
void aisync_loading(void);
|
||||
// This is called when that motion is successfully loaded and it has to be re-registered because now the duration etc is known.
|
||||
void aisync_loaded(void);
|
||||
|
||||
public:
|
||||
// Virtual functions of AISyncClientMotion.
|
||||
// These are defined by classes derived from LLMotion (which is derived from this class).
|
||||
virtual BOOL getLoop() = 0;
|
||||
virtual F32 getDuration() = 0;
|
||||
virtual F32 getAnimTime(void) const = 0;
|
||||
virtual F32 getRuntime(void) const = 0;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class LLMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLMotion
|
||||
class LLMotion : public AISyncClientMotion
|
||||
{
|
||||
friend class LLMotionController;
|
||||
|
||||
@@ -66,7 +135,7 @@ public:
|
||||
};
|
||||
|
||||
// Constructor
|
||||
LLMotion(const LLUUID &id);
|
||||
LLMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLMotion();
|
||||
@@ -114,7 +183,22 @@ protected:
|
||||
BOOL isActive() { return mActive; }
|
||||
public:
|
||||
void activate(F32 time);
|
||||
|
||||
|
||||
//<singu>
|
||||
// Returns the time that this motion has been running.
|
||||
virtual F32 getRuntime(void) const;
|
||||
|
||||
// Return the current time (in seconds since creation of the controller).
|
||||
virtual F32 getAnimTime(void) const;
|
||||
|
||||
// This is called when a motion is to be activated, but might need synchronization.
|
||||
// It adjusts the start time to match that of other motions in the same synchronization group that were already started.
|
||||
F32 syncActivationTime(F32 time);
|
||||
|
||||
// Accessor.
|
||||
LLMotionController* getController(void) const { return mController; }
|
||||
//</singu>
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// animation callbacks to be implemented by subclasses
|
||||
@@ -181,6 +265,9 @@ protected:
|
||||
//-------------------------------------------------------------------------
|
||||
std::string mName; // instance name assigned by motion controller
|
||||
LLUUID mID;
|
||||
//<singu>
|
||||
LLMotionController* mController;
|
||||
//</singu>
|
||||
|
||||
F32 mActivationTimestamp; // time when motion was activated
|
||||
F32 mStopTimestamp; // time when motion was told to stop
|
||||
@@ -199,9 +286,9 @@ protected:
|
||||
class LLTestMotion : public LLMotion
|
||||
{
|
||||
public:
|
||||
LLTestMotion(const LLUUID &id) : LLMotion(id){}
|
||||
LLTestMotion(LLUUID const& id, LLMotionController* controller) : LLMotion(id, controller){}
|
||||
~LLTestMotion() {}
|
||||
static LLMotion *create(const LLUUID& id) { return new LLTestMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLTestMotion(id, controller); }
|
||||
BOOL getLoop() { return FALSE; }
|
||||
F32 getDuration() { return 0.0f; }
|
||||
F32 getEaseInDuration() { return 0.0f; }
|
||||
@@ -223,9 +310,9 @@ public:
|
||||
class LLNullMotion : public LLMotion
|
||||
{
|
||||
public:
|
||||
LLNullMotion(const LLUUID &id) : LLMotion(id) {}
|
||||
LLNullMotion(LLUUID const& id, LLMotionController* controller) : LLMotion(id, controller) {}
|
||||
~LLNullMotion() {}
|
||||
static LLMotion *create(const LLUUID &id) { return new LLNullMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLNullMotion(id, controller); }
|
||||
|
||||
// motions must specify whether or not they loop
|
||||
/*virtual*/ BOOL getLoop() { return TRUE; }
|
||||
@@ -266,5 +353,41 @@ public:
|
||||
// called when a motion is deactivated
|
||||
/*virtual*/ void onDeactivate() {}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AIMaskedMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// These motions have a bit assigned in LLMotionController::mActiveMask
|
||||
// that is set and uset upon activation/deactivation.
|
||||
|
||||
// This must be in the same order as ANIM_AGENT_BODY_NOISE_ID through ANIM_AGENT_WALK_ADJUST_ID in llvoavatar.cpp.
|
||||
U32 const ANIM_AGENT_BODY_NOISE = 0x001;
|
||||
U32 const ANIM_AGENT_BREATHE_ROT = 0x002;
|
||||
U32 const ANIM_AGENT_PHYSICS_MOTION = 0x004;
|
||||
U32 const ANIM_AGENT_EDITING = 0x008;
|
||||
U32 const ANIM_AGENT_EYE = 0x010;
|
||||
U32 const ANIM_AGENT_FLY_ADJUST = 0x020;
|
||||
U32 const ANIM_AGENT_HAND_MOTION = 0x040;
|
||||
U32 const ANIM_AGENT_HEAD_ROT = 0x080;
|
||||
U32 const ANIM_AGENT_PELVIS_FIX = 0x100;
|
||||
U32 const ANIM_AGENT_TARGET = 0x200;
|
||||
U32 const ANIM_AGENT_WALK_ADJUST = 0x400;
|
||||
|
||||
class AIMaskedMotion : public LLMotion
|
||||
{
|
||||
private:
|
||||
U32 mMaskBit;
|
||||
|
||||
public:
|
||||
AIMaskedMotion(LLUUID const& id, LLMotionController* controller, U32 mask_bit) : LLMotion(id, controller), mMaskBit(mask_bit) { }
|
||||
|
||||
/*virtual*/ BOOL onActivate();
|
||||
/*virtual*/ void onDeactivate();
|
||||
|
||||
U32 getMaskBit(void) const { return mMaskBit; }
|
||||
};
|
||||
|
||||
#endif // LL_LLMOTION_H
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ void LLMotionRegistry::markBad( const LLUUID& id )
|
||||
//-----------------------------------------------------------------------------
|
||||
// createMotion()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLMotion *LLMotionRegistry::createMotion( const LLUUID &id )
|
||||
LLMotion* LLMotionRegistry::createMotion(LLUUID const& id, LLMotionController* controller)
|
||||
{
|
||||
LLMotionConstructor constructor = get_if_there(mMotionTable, id, LLMotionConstructor(NULL));
|
||||
LLMotion* motion = NULL;
|
||||
@@ -105,11 +105,11 @@ LLMotion *LLMotionRegistry::createMotion( const LLUUID &id )
|
||||
if ( constructor == NULL )
|
||||
{
|
||||
// *FIX: need to replace with a better default scheme. RN
|
||||
motion = LLKeyframeMotion::create(id);
|
||||
motion = LLKeyframeMotion::create(id, controller);
|
||||
}
|
||||
else
|
||||
{
|
||||
motion = constructor(id);
|
||||
motion = constructor(id, controller);
|
||||
}
|
||||
|
||||
return motion;
|
||||
@@ -126,18 +126,22 @@ LLMotion *LLMotionRegistry::createMotion( const LLUUID &id )
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLMotionController::LLMotionController()
|
||||
: mTimeFactor(sCurrentTimeFactor),
|
||||
: mIsSelf(FALSE),
|
||||
mTimeFactor(sCurrentTimeFactor),
|
||||
mCharacter(NULL),
|
||||
mAnimTime(0.f),
|
||||
mActiveMask(0),
|
||||
mDisableSyncing(0),
|
||||
mHidden(false),
|
||||
mHaveVisibleSyncedMotions(false),
|
||||
mPrevTimerElapsed(0.f),
|
||||
mAnimTime(0.f),
|
||||
mLastTime(0.0f),
|
||||
mHasRunOnce(FALSE),
|
||||
mPaused(FALSE),
|
||||
mPauseTime(0.f),
|
||||
mTimeStep(0.f),
|
||||
mTimeStepCount(0),
|
||||
mLastInterp(0.f),
|
||||
mIsSelf(FALSE)
|
||||
mLastInterp(0.f)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -168,7 +172,15 @@ void LLMotionController::deleteAllMotions()
|
||||
mLoadingMotions.clear();
|
||||
mLoadedMotions.clear();
|
||||
mActiveMotions.clear();
|
||||
|
||||
//<singu>
|
||||
mActiveMask = 0;
|
||||
for_each(mDeprecatedMotions.begin(), mDeprecatedMotions.end(), DeletePointer());
|
||||
mDeprecatedMotions.clear();
|
||||
for (motion_map_t::iterator iter = mAllMotions.begin(); iter != mAllMotions.end(); ++iter)
|
||||
{
|
||||
iter->second->unregister_client();
|
||||
}
|
||||
//</singu>
|
||||
for_each(mAllMotions.begin(), mAllMotions.end(), DeletePairedPointer());
|
||||
mAllMotions.clear();
|
||||
}
|
||||
@@ -178,26 +190,19 @@ void LLMotionController::deleteAllMotions()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLMotionController::purgeExcessMotions()
|
||||
{
|
||||
if (mLoadedMotions.size() > MAX_MOTION_INSTANCES)
|
||||
//<singu>
|
||||
// The old code attempted to remove non-active motions from mDeprecatedMotions,
|
||||
// but that is nonsense: there are no motions in mDeprecatedMotions that are not active.
|
||||
if (mLoadedMotions.size() <= MAX_MOTION_INSTANCES)
|
||||
{
|
||||
// clean up deprecated motions
|
||||
for (motion_set_t::iterator deprecated_motion_it = mDeprecatedMotions.begin();
|
||||
deprecated_motion_it != mDeprecatedMotions.end(); )
|
||||
{
|
||||
motion_set_t::iterator cur_iter = deprecated_motion_it++;
|
||||
LLMotion* cur_motionp = *cur_iter;
|
||||
if (!isMotionActive(cur_motionp))
|
||||
{
|
||||
// Motion is deprecated so we know it's not cannonical,
|
||||
// we can safely remove the instance
|
||||
removeMotionInstance(cur_motionp); // modifies mDeprecatedMotions
|
||||
mDeprecatedMotions.erase(cur_iter);
|
||||
}
|
||||
}
|
||||
// Speed up, no need to create motions_to_kill.
|
||||
return;
|
||||
}
|
||||
//</singu>
|
||||
|
||||
std::set<LLUUID> motions_to_kill;
|
||||
if (mLoadedMotions.size() > MAX_MOTION_INSTANCES)
|
||||
|
||||
if (1) // Singu: leave indentation alone...
|
||||
{
|
||||
// too many motions active this frame, kill all blenders
|
||||
mPoseBlender.clearBlenders();
|
||||
@@ -308,24 +313,44 @@ BOOL LLMotionController::registerMotion( const LLUUID& id, LLMotionConstructor c
|
||||
void LLMotionController::removeMotion( const LLUUID& id)
|
||||
{
|
||||
LLMotion* motionp = findMotion(id);
|
||||
mAllMotions.erase(id);
|
||||
removeMotionInstance(motionp);
|
||||
//<singu>
|
||||
// If a motion is erased from mAllMotions, it must be deleted.
|
||||
if (motionp)
|
||||
{
|
||||
mAllMotions.erase(id);
|
||||
removeMotionInstance(motionp);
|
||||
delete motionp;
|
||||
}
|
||||
//</singu>
|
||||
}
|
||||
|
||||
// removes instance of a motion from all runtime structures, but does
|
||||
// not erase entry by ID, as this could be a duplicate instance
|
||||
// use removeMotion(id) to remove all references to a given motion by id.
|
||||
// use removeMotion(id) to remove a reference to a given motion by id
|
||||
// (that will not remove (active) deprecated motions).
|
||||
void LLMotionController::removeMotionInstance(LLMotion* motionp)
|
||||
{
|
||||
if (motionp)
|
||||
{
|
||||
llassert(findMotion(motionp->getID()) != motionp);
|
||||
if (motionp->isActive())
|
||||
motionp->deactivate();
|
||||
mLoadingMotions.erase(motionp);
|
||||
mLoadedMotions.erase(motionp);
|
||||
mActiveMotions.remove(motionp);
|
||||
delete motionp;
|
||||
//<singu>
|
||||
// Deactivation moved here. Only delete motionp when it is being removed from mDeprecatedMotions.
|
||||
if (motionp->isActive())
|
||||
{
|
||||
motionp->deactivate();
|
||||
// If a motion is deactivated, it must be removed from mDeprecatedMotions if there.
|
||||
motion_set_t::iterator found_it = mDeprecatedMotions.find(motionp);
|
||||
if (found_it != mDeprecatedMotions.end())
|
||||
{
|
||||
mDeprecatedMotions.erase(found_it);
|
||||
// If a motion is erased from mDeprecatedMotions, it must be deleted.
|
||||
delete motionp;
|
||||
}
|
||||
}
|
||||
//</singu>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +366,7 @@ LLMotion* LLMotionController::createMotion( const LLUUID &id )
|
||||
if (!motion)
|
||||
{
|
||||
// look up constructor and create it
|
||||
motion = sRegistry.createMotion(id);
|
||||
motion = sRegistry.createMotion(id, this);
|
||||
if (!motion)
|
||||
{
|
||||
return NULL;
|
||||
@@ -393,6 +418,7 @@ BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset)
|
||||
if (motion
|
||||
&& !mPaused
|
||||
&& motion->canDeprecate()
|
||||
&& motion->isActive() // singu: do not deprecate motions that are not active.
|
||||
&& motion->getFadeWeight() > 0.01f // not LOD-ed out
|
||||
&& (motion->isBlending() || motion->getStopTime() != 0.f))
|
||||
{
|
||||
@@ -418,7 +444,19 @@ BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset)
|
||||
}
|
||||
|
||||
// llinfos << "Starting motion " << name << llendl;
|
||||
return activateMotionInstance(motion, mAnimTime - start_offset);
|
||||
//<singu>
|
||||
F32 start_time = mAnimTime - start_offset;
|
||||
if (!mDisableSyncing)
|
||||
{
|
||||
start_time = motion->syncActivationTime(start_time);
|
||||
}
|
||||
++mDisableSyncing;
|
||||
//</singu>
|
||||
BOOL res = activateMotionInstance(motion, start_time);
|
||||
//<singu>
|
||||
--mDisableSyncing;
|
||||
//</singu>
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -774,7 +812,19 @@ void LLMotionController::updateLoadingMotions()
|
||||
// this motion should be playing
|
||||
if (!motionp->isStopped())
|
||||
{
|
||||
activateMotionInstance(motionp, mAnimTime);
|
||||
//<singu>
|
||||
F32 start_time = mAnimTime;
|
||||
if (!mDisableSyncing)
|
||||
{
|
||||
motionp->aisync_loaded();
|
||||
start_time = motionp->syncActivationTime(start_time);
|
||||
}
|
||||
++mDisableSyncing;
|
||||
//</singu>
|
||||
activateMotionInstance(motionp, start_time);
|
||||
//<singu>
|
||||
--mDisableSyncing;
|
||||
//</singu>
|
||||
}
|
||||
}
|
||||
else if (status == LLMotion::STATUS_FAILURE)
|
||||
@@ -782,12 +832,15 @@ void LLMotionController::updateLoadingMotions()
|
||||
llinfos << "Motion " << motionp->getID() << " init failed." << llendl;
|
||||
sRegistry.markBad(motionp->getID());
|
||||
mLoadingMotions.erase(curiter);
|
||||
motion_set_t::iterator found_it = mDeprecatedMotions.find(motionp);
|
||||
if (found_it != mDeprecatedMotions.end())
|
||||
{
|
||||
mDeprecatedMotions.erase(found_it);
|
||||
}
|
||||
// Singu note: a motion in mLoadingMotions will not be in mActiveMotions
|
||||
// and therefore not be in mDeprecatedMotions. So, we don't have to
|
||||
// check for it's existence there.
|
||||
llassert(mDeprecatedMotions.find(motionp) == mDeprecatedMotions.end());
|
||||
mAllMotions.erase(motionp->getID());
|
||||
//<singu>
|
||||
// Make sure we're not registered anymore.
|
||||
motionp->unregister_client();
|
||||
//</singu>
|
||||
delete motionp;
|
||||
}
|
||||
}
|
||||
@@ -821,8 +874,15 @@ void LLMotionController::updateMotions(bool force_update)
|
||||
{
|
||||
F32 time_interval = fmodf(update_time, mTimeStep);
|
||||
|
||||
// always animate *ahead* of actual time
|
||||
S32 quantum_count = llmax(0, llfloor((update_time - time_interval) / mTimeStep)) + 1;
|
||||
//<singu>
|
||||
// This old code is nonsense.
|
||||
//S32 quantum_count = llmax(0, llround((update_time - time_interval) / mTimeStep)) + 1;
|
||||
// (update_time - time_interval) / mTimeStep is an integer! We need llround to get rid of floating point errors, not llfloor.
|
||||
// Moreover, just rounding off to the nearest integer with llround(update_time / mTimeStep) makes a lot more sense:
|
||||
// it is the best we can do to get as close to what we should draw as possible.
|
||||
// However, mAnimTime may only be incremented; therefore make sure of that with the llmax.
|
||||
S32 quantum_count = llmax(llround(update_time / mTimeStep), llceil(mAnimTime / mTimeStep));
|
||||
//</singu>
|
||||
if (quantum_count == mTimeStepCount)
|
||||
{
|
||||
// we're still in same time quantum as before, so just interpolate and exit
|
||||
@@ -848,7 +908,8 @@ void LLMotionController::updateMotions(bool force_update)
|
||||
}
|
||||
else
|
||||
{
|
||||
mAnimTime = update_time;
|
||||
// Singu note: mAnimTime may never be set back in time.
|
||||
mAnimTime = llmax(mAnimTime, update_time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -915,6 +976,12 @@ BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time)
|
||||
|
||||
if (mLoadingMotions.find(motion) != mLoadingMotions.end())
|
||||
{
|
||||
//<singu>
|
||||
if (!syncing_disabled())
|
||||
{
|
||||
motion->aisync_loading();
|
||||
}
|
||||
//</singu>
|
||||
// we want to start this motion, but we can't yet, so flag it as started
|
||||
motion->setStopped(FALSE);
|
||||
// report pending animations as activated
|
||||
@@ -970,18 +1037,16 @@ BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time)
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLMotionController::deactivateMotionInstance(LLMotion *motion)
|
||||
{
|
||||
motion->deactivate();
|
||||
|
||||
motion_set_t::iterator found_it = mDeprecatedMotions.find(motion);
|
||||
if (found_it != mDeprecatedMotions.end())
|
||||
{
|
||||
// deprecated motions need to be completely excised
|
||||
removeMotionInstance(motion);
|
||||
mDeprecatedMotions.erase(found_it);
|
||||
removeMotionInstance(motion); // singu note: this deactivates motion and removes it from mDeprecatedMotions.
|
||||
}
|
||||
else
|
||||
{
|
||||
// for motions that we are keeping, simply remove from active queue
|
||||
motion->deactivate(); // singu note: moved here from the top of the function.
|
||||
mActiveMotions.remove(motion);
|
||||
}
|
||||
|
||||
@@ -1049,11 +1114,26 @@ void LLMotionController::dumpMotions()
|
||||
state_string += std::string("L");
|
||||
if (std::find(mActiveMotions.begin(), mActiveMotions.end(), motion)!=mActiveMotions.end())
|
||||
state_string += std::string("A");
|
||||
if (mDeprecatedMotions.find(motion) != mDeprecatedMotions.end())
|
||||
state_string += std::string("D");
|
||||
llassert(mDeprecatedMotions.find(motion) == mDeprecatedMotions.end()); // singu: it's impossible that a motion is in mAllMotions and mDeprecatedMotions at the same time.
|
||||
llinfos << gAnimLibrary.animationName(id) << " " << state_string << llendl;
|
||||
|
||||
}
|
||||
//<singu>
|
||||
// Also dump the deprecated motions.
|
||||
for (motion_set_t::iterator iter = mDeprecatedMotions.begin();
|
||||
iter != mDeprecatedMotions.end(); ++iter)
|
||||
{
|
||||
std::string state_string;
|
||||
LLMotion* motion = *iter;
|
||||
LLUUID id = motion->getID();
|
||||
llassert(mLoadingMotions.find(motion) == mLoadingMotions.end());
|
||||
if (mLoadedMotions.find(motion) != mLoadedMotions.end())
|
||||
state_string += std::string("L");
|
||||
if (std::find(mActiveMotions.begin(), mActiveMotions.end(), motion)!=mActiveMotions.end())
|
||||
state_string += std::string("A");
|
||||
state_string += "D";
|
||||
llinfos << gAnimLibrary.animationName(id) << " " << state_string << llendl;
|
||||
}
|
||||
//</singu>
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1061,11 +1141,11 @@ void LLMotionController::dumpMotions()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLMotionController::deactivateAllMotions()
|
||||
{
|
||||
for (motion_map_t::iterator iter = mAllMotions.begin();
|
||||
iter != mAllMotions.end(); iter++)
|
||||
// Singu note: this must run over mActiveMotions: other motions are not active,
|
||||
// and running over mAllMotions will miss the ones in mDeprecatedMotions.
|
||||
for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end();)
|
||||
{
|
||||
LLMotion* motionp = iter->second;
|
||||
deactivateMotionInstance(motionp);
|
||||
deactivateMotionInstance(*iter++); // This might invalidate iter by erasing it from mActiveMotions.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1086,8 +1166,7 @@ void LLMotionController::flushAllMotions()
|
||||
active_motions.push_back(std::make_pair(motionp->getID(),dtime));
|
||||
motionp->deactivate(); // don't call deactivateMotionInstance() because we are going to reactivate it
|
||||
}
|
||||
mActiveMotions.clear();
|
||||
|
||||
|
||||
// delete all motion instances
|
||||
deleteAllMotions();
|
||||
|
||||
@@ -1096,13 +1175,136 @@ void LLMotionController::flushAllMotions()
|
||||
mCharacter->removeAnimationData("Hand Pose");
|
||||
|
||||
// restart motions
|
||||
//<singu>
|
||||
// Because we called motionp->deactivate() above, instead of deactivateMotionInstance(),
|
||||
// prevent calling AISyncClientMotion::activateInstance in startMotion below.
|
||||
disable_syncing();
|
||||
//</singu>
|
||||
for (std::vector<std::pair<LLUUID,F32> >::iterator iter = active_motions.begin();
|
||||
iter != active_motions.end(); ++iter)
|
||||
{
|
||||
startMotion(iter->first, iter->second);
|
||||
}
|
||||
//<singu>
|
||||
enable_syncing();
|
||||
//</singu>
|
||||
}
|
||||
|
||||
//<singu>
|
||||
//-----------------------------------------------------------------------------
|
||||
// toggle_hidden()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLMotionController::toggle_hidden(void)
|
||||
{
|
||||
mHaveVisibleSyncedMotions = mHidden; // Default is false if we just became invisible (otherwise this value isn't used).
|
||||
mHidden = !mHidden;
|
||||
synceventset_t const visible = mHidden ? 0 : 4;
|
||||
|
||||
// Run over all motions.
|
||||
for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end(); ++iter)
|
||||
{
|
||||
LLMotion* motionp = *iter;
|
||||
AISyncServer* server = motionp->server();
|
||||
if (server && !server->never_synced() && motionp->isActive()) // Skip motions that aren't synchronized at all or that are not active.
|
||||
{
|
||||
bool visible_before = server->events_with_at_least_one_client_ready() & 4;
|
||||
server->ready(4, visible, motionp); // Mark that now we are visible or no longer visible.
|
||||
bool visible_after = server->events_with_at_least_one_client_ready() & 4;
|
||||
if (visible_after) // Are there any synchronized motions (left) that ARE visible?
|
||||
{
|
||||
mHaveVisibleSyncedMotions = true;
|
||||
}
|
||||
if (visible_before != visible_after)
|
||||
{
|
||||
// The group as a whole now might need to change whether or not it is animated.
|
||||
AISyncServer::client_list_t const& clients = server->getClients();
|
||||
for (AISyncServer::client_list_t::const_iterator client = clients.begin(); client != clients.end(); ++client)
|
||||
{
|
||||
LLMotion* motion = dynamic_cast<LLMotion*>(client->mClientPtr);
|
||||
if (!motion)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
LLMotionController* controller = motion->getController();
|
||||
if (controller == this)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (visible_after)
|
||||
{
|
||||
// Us becoming visible means that all synchronized avatars need to be animated again too.
|
||||
controller->setHaveVisibleSyncedMotions();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Us becoming hidden means that all synchronized avatars might stop animating.
|
||||
controller->refresh_hidden(); // It is extremely unlikely, but harmless, to call this twice on the same controller.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLMotionController::refresh_hidden(void)
|
||||
{
|
||||
mHaveVisibleSyncedMotions = !mHidden;
|
||||
|
||||
// Run over all motions.
|
||||
for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end(); ++iter)
|
||||
{
|
||||
LLMotion* motionp = *iter;
|
||||
AISyncServer* server = motionp->server();
|
||||
if (server && !server->never_synced() && motionp->isActive()) // Skip motions that aren't synchronized at all or that are not active.
|
||||
{
|
||||
bool visible_after = server->events_with_at_least_one_client_ready() & 4;
|
||||
if (visible_after) // Are there any synchronized motions (left) that ARE visible?
|
||||
{
|
||||
mHaveVisibleSyncedMotions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLMotionController::pauseAllSyncedCharacters(std::vector<LLAnimPauseRequest>& avatar_pause_handles)
|
||||
{
|
||||
// Run over all motions.
|
||||
for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end(); ++iter)
|
||||
{
|
||||
LLMotion* motionp = *iter;
|
||||
AISyncServer* server = motionp->server();
|
||||
if (server && !server->never_synced() && motionp->isActive()) // Skip motions that aren't synchronized at all or that are not active.
|
||||
{
|
||||
// Run over all clients of the found servers.
|
||||
AISyncServer::client_list_t const& clients = server->getClients();
|
||||
for (AISyncServer::client_list_t::const_iterator client = clients.begin(); client != clients.end(); ++client)
|
||||
{
|
||||
LLMotion* motion = dynamic_cast<LLMotion*>(client->mClientPtr);
|
||||
if (!motion)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
LLMotionController* controller = motion->getController();
|
||||
if (controller == this)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
controller->requestPause(avatar_pause_handles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLMotionController::requestPause(std::vector<LLAnimPauseRequest>& avatar_pause_handles)
|
||||
{
|
||||
if (mCharacter)
|
||||
{
|
||||
mCharacter->requestPause(avatar_pause_handles);
|
||||
}
|
||||
}
|
||||
|
||||
//</singu>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// pause()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -51,11 +51,14 @@
|
||||
// This is necessary because llcharacter.h includes this file.
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLCharacter;
|
||||
class LLMotionController;
|
||||
class LLPauseRequestHandle;
|
||||
typedef LLPointer<LLPauseRequestHandle> LLAnimPauseRequest;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLMotionRegistry
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef LLMotion*(*LLMotionConstructor)(const LLUUID &id);
|
||||
typedef LLMotion* (*LLMotionConstructor)(LLUUID const& id, LLMotionController*);
|
||||
|
||||
class LLMotionRegistry
|
||||
{
|
||||
@@ -72,7 +75,7 @@ public:
|
||||
|
||||
// creates a new instance of a named motion
|
||||
// returns NULL motion is not registered
|
||||
LLMotion *createMotion( const LLUUID &id );
|
||||
LLMotion* createMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// initialization of motion failed, don't try to create this motion again
|
||||
void markBad( const LLUUID& id );
|
||||
@@ -115,7 +118,6 @@ public:
|
||||
|
||||
// unregisters a motion with the controller
|
||||
// (actually just forwards call to motion registry)
|
||||
// returns true if successfull
|
||||
void removeMotion( const LLUUID& id );
|
||||
|
||||
// start motion
|
||||
@@ -150,10 +152,20 @@ public:
|
||||
//Flush is a liar.
|
||||
void deactivateAllMotions();
|
||||
|
||||
//<singu>
|
||||
void activated(U32 bit) { mActiveMask |= bit; }
|
||||
void deactivated(U32 bit) { mActiveMask &= ~bit; }
|
||||
bool isactive(U32 bit) const { return (mActiveMask & bit) != 0; }
|
||||
//</singu>
|
||||
|
||||
// pause and continue all motions
|
||||
void pauseAllMotions();
|
||||
void unpauseAllMotions();
|
||||
BOOL isPaused() const { return mPaused; }
|
||||
//<singu>
|
||||
void requestPause(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
|
||||
void pauseAllSyncedCharacters(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
|
||||
//</singu>
|
||||
|
||||
void setTimeStep(F32 step);
|
||||
|
||||
@@ -180,7 +192,10 @@ protected:
|
||||
// internal operations act on motion instances directly
|
||||
// as there can be duplicate motions per id during blending overlap
|
||||
void deleteAllMotions();
|
||||
// singu: LLMotion needs access to activateMotionInstance.
|
||||
public:
|
||||
BOOL activateMotionInstance(LLMotion *motion, F32 time);
|
||||
protected:
|
||||
BOOL deactivateMotionInstance(LLMotion *motion);
|
||||
void deprecateMotionInstance(LLMotion* motion);
|
||||
BOOL stopMotionInstance(LLMotion *motion, BOOL stop_imemdiate);
|
||||
@@ -205,10 +220,13 @@ protected:
|
||||
// Life cycle of an animation:
|
||||
//
|
||||
// Animations are instantiated and immediately put in the mAllMotions map for their entire lifetime.
|
||||
// Singu note: that is not true, they are moved to mDeprecatedMotions (often) for the last part of their lifetime.
|
||||
// If the animations depend on any asset data, the appropriate data is fetched from the data server,
|
||||
// and the animation is put on the mLoadingMotions list.
|
||||
// Once an animations is loaded, it will be initialized and put on the mLoadedMotions list.
|
||||
// Any animation that is currently playing also sits in the mActiveMotions list.
|
||||
// Singu note: animations are only put in mDeprecatedMotions if and while they are playing,
|
||||
// therefore animations in mDeprecatedMotions will be (must be) active and in mActiveMotions.
|
||||
|
||||
typedef std::map<LLUUID, LLMotion*> motion_map_t;
|
||||
motion_map_t mAllMotions;
|
||||
@@ -217,7 +235,13 @@ protected:
|
||||
motion_set_t mLoadedMotions;
|
||||
motion_list_t mActiveMotions;
|
||||
motion_set_t mDeprecatedMotions;
|
||||
|
||||
|
||||
//<singu>
|
||||
U32 mActiveMask;
|
||||
int mDisableSyncing; // Set while LLMotion::onActivate (and onDeactivate) are called for this controller.
|
||||
bool mHidden; // The value of the last call to hidden().
|
||||
bool mHaveVisibleSyncedMotions; // Set when we are synchronized with one or more motions of a controller that is not hidden.
|
||||
//</singu>
|
||||
LLFrameTimer mTimer;
|
||||
F32 mPrevTimerElapsed;
|
||||
F32 mAnimTime;
|
||||
@@ -230,6 +254,26 @@ protected:
|
||||
F32 mLastInterp;
|
||||
|
||||
U8 mJointSignature[2][LL_CHARACTER_MAX_JOINTS];
|
||||
|
||||
//<singu>
|
||||
public:
|
||||
// Internal administration for AISync.
|
||||
void disable_syncing(void) { mDisableSyncing += 100; }
|
||||
void enable_syncing(void) { mDisableSyncing -= 100; }
|
||||
bool syncing_disabled(void) const { return mDisableSyncing >= 100; }
|
||||
|
||||
// Accessors needed for synchronization.
|
||||
F32 getAnimTime(void) const { return mAnimTime; }
|
||||
bool isHidden(void) const { return mHidden; }
|
||||
|
||||
// Called often. Should return false if we still need to keep updating our motions even if we're not visible.
|
||||
bool hidden(bool not_visible) { if (mHidden != not_visible) toggle_hidden(); return !mHaveVisibleSyncedMotions; }
|
||||
|
||||
private:
|
||||
void toggle_hidden(void);
|
||||
void refresh_hidden(void);
|
||||
void setHaveVisibleSyncedMotions(void) { mHaveVisibleSyncedMotions = true; }
|
||||
//</singu>
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -52,7 +52,7 @@ const F32 TORSO_ROT_FRACTION = 0.5f;
|
||||
// LLTargetingMotion()
|
||||
// Class Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
LLTargetingMotion::LLTargetingMotion(const LLUUID &id) : LLMotion(id)
|
||||
LLTargetingMotion::LLTargetingMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_TARGET)
|
||||
{
|
||||
mCharacter = NULL;
|
||||
mName = "targeting";
|
||||
@@ -99,14 +99,6 @@ LLMotion::LLMotionInitStatus LLTargetingMotion::onInitialize(LLCharacter *charac
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLTargetingMotion::onActivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLTargetingMotion::onActivate()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLTargetingMotion::onUpdate()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -166,12 +158,4 @@ BOOL LLTargetingMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLTargetingMotion::onDeactivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLTargetingMotion::onDeactivate()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// End
|
||||
|
||||
@@ -48,11 +48,11 @@
|
||||
// class LLTargetingMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLTargetingMotion :
|
||||
public LLMotion
|
||||
public AIMaskedMotion
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLTargetingMotion(const LLUUID &id);
|
||||
LLTargetingMotion(LLUUID const& id, LLMotionController* controller);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLTargetingMotion();
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLTargetingMotion(id); }
|
||||
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLTargetingMotion(id, controller); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -96,19 +96,11 @@ public:
|
||||
// must return true to indicate success and be available for activation
|
||||
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
|
||||
|
||||
// called when a motion is activated
|
||||
// must return TRUE to indicate success, or else
|
||||
// it will be deactivated
|
||||
virtual BOOL onActivate();
|
||||
|
||||
// called per time step
|
||||
// must return TRUE while it is active, and
|
||||
// must return FALSE when the motion is completed.
|
||||
virtual BOOL onUpdate(F32 time, U8* joint_mask);
|
||||
|
||||
// called when a motion is deactivated
|
||||
virtual void onDeactivate();
|
||||
|
||||
public:
|
||||
|
||||
LLCharacter *mCharacter;
|
||||
|
||||
@@ -20,6 +20,7 @@ set(llcommon_SOURCE_FILES
|
||||
aialert.cpp
|
||||
aifile.cpp
|
||||
aiframetimer.cpp
|
||||
aisyncclient.cpp
|
||||
aithreadid.cpp
|
||||
imageids.cpp
|
||||
indra_constants.cpp
|
||||
@@ -59,7 +60,6 @@ set(llcommon_SOURCE_FILES
|
||||
llformat.cpp
|
||||
llframetimer.cpp
|
||||
llheartbeat.cpp
|
||||
llindraconfigfile.cpp
|
||||
llinitparam.cpp
|
||||
llinstancetracker.cpp
|
||||
llliveappconfig.cpp
|
||||
@@ -112,11 +112,13 @@ set(llcommon_HEADER_FILES
|
||||
aifile.h
|
||||
aiframetimer.h
|
||||
airecursive.h
|
||||
aisyncclient.h
|
||||
aithreadid.h
|
||||
aithreadsafe.h
|
||||
bitpack.h
|
||||
ctype_workaround.h
|
||||
doublelinkedlist.h
|
||||
fix_macros.h
|
||||
imageids.h
|
||||
indra_constants.h
|
||||
linden_common.h
|
||||
@@ -183,7 +185,6 @@ set(llcommon_HEADER_FILES
|
||||
llheartbeat.h
|
||||
llhttpstatuscodes.h
|
||||
llindexedqueue.h
|
||||
llindraconfigfile.h
|
||||
llinitparam.h
|
||||
llinstancetracker.h
|
||||
llkeythrottle.h
|
||||
@@ -253,7 +254,6 @@ set(llcommon_HEADER_FILES
|
||||
metapropertyt.h
|
||||
reflective.h
|
||||
reflectivet.h
|
||||
roles_constants.h
|
||||
stdenums.h
|
||||
stdtypes.h
|
||||
string_table.h
|
||||
@@ -270,6 +270,9 @@ list(APPEND llcommon_SOURCE_FILES ${cwdebug_SOURCE_FILES})
|
||||
list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
|
||||
|
||||
add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
|
||||
if(WINDOWS)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
|
||||
endif(WINDOWS)
|
||||
add_dependencies(llcommon prepare)
|
||||
target_link_libraries(
|
||||
llcommon
|
||||
|
||||
698
indra/llcommon/aisyncclient.cpp
Normal file
698
indra/llcommon/aisyncclient.cpp
Normal file
@@ -0,0 +1,698 @@
|
||||
/**
|
||||
* @file aisyncclient.cpp
|
||||
*
|
||||
* Copyright (c) 2013, Aleric Inglewood.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution.
|
||||
*
|
||||
* CHANGELOG
|
||||
* and additional copyright holders.
|
||||
*
|
||||
* 13/12/2013
|
||||
* - Initial version, written by Aleric Inglewood @ SL
|
||||
*/
|
||||
|
||||
/*
|
||||
* AISyncClient : the base class of a client object (LLMotion) that needs to be informed
|
||||
* of the state of other such objects and/or to poll a server object about the state of
|
||||
* other such objects, in order to be and stay synchronized with those other objects.
|
||||
* In the case of an LLMotion (animation), all clients would be started and stopped at
|
||||
* the same time, as long as they are part of the same synchronization group (AISyncServer).
|
||||
*
|
||||
* AISyncKey: object that determines what synchronization group a client belongs to.
|
||||
* When a new client is created, a new AISyncKey is created too, using information from
|
||||
* the client, the current frame number and the current frame time. If two AISyncKey
|
||||
* compare equal, using operator==(AISyncKey const& key1, AISyncKey const& key2),
|
||||
* then the clients that created them need to be synchronized.
|
||||
*
|
||||
* AISyncServer: object that represents a group of clients that need to be synchronized:
|
||||
* it's a wrapper around a std::list<AISyncClientData> with pointers to all the clients
|
||||
* that need to be synchronized. It also stores the AISyncKey of the first (oldest) client
|
||||
* that was added. Clients with keys that compare equal to that will be added.
|
||||
* If a client is added with a synckeytype_t that is larger then it always replaces
|
||||
* the existing key however.
|
||||
*
|
||||
* AISyncServerMap: A wrapper around std::list<boost::intrusive_ptr<AISyncServer> >
|
||||
* that stores pointers to all currently existing AISyncServer objects. New entries
|
||||
* are added at the end, so the oldest key is at the front.
|
||||
*
|
||||
* AISyncServerMap list + - - - - - - + - - - - - - + ... The AISyncServerMap is
|
||||
* | | | a list with refcounted
|
||||
* V V V pointers to AISyncServers.
|
||||
* AISyncClient +--> AISyncServer
|
||||
* | <--- list key ---> AISyncKey Each AISyncServer is a
|
||||
* DerivedClient . list of normal pointers
|
||||
* . AISyncClients and one
|
||||
* <--- . pointer to a AISyncKey.
|
||||
* Each AISyncClient is the
|
||||
* base class of a DerivedClient
|
||||
* and pointers back to the
|
||||
* server with a refcounted
|
||||
* pointer.
|
||||
*
|
||||
* A new client is passed to the AISyncServerMap to be stored in a new or existing AISyncServer
|
||||
* object, using the key that the client produces. A boost::intrusive_ptr<AISyncServer> member
|
||||
* of the client is set to point to this server.
|
||||
*
|
||||
* The lifetime of the server objects is determined by the intrusive_ptr objects that
|
||||
* point to it: all the clients (which have an externally determined lifetime) and one
|
||||
* pointer in the AISyncServerMap. However, regularly a check is done on all servers in
|
||||
* the list to find expired servers: objects with keys older than two frames and older
|
||||
* than 0.1 seconds; if such a server is found and it has zero or one client, then the
|
||||
* client is unregistered and the pointer (and thus the server) removed from the
|
||||
* AISyncServerMap. If it has two or more clients then the entry is kept until both
|
||||
* clients are removed, which therefore can only be detected in intrusive_ptr_release
|
||||
* which only has access to the server object. The server then is removed from the list
|
||||
* by searching through it for the pointer to the server.
|
||||
*/
|
||||
|
||||
#include "sys.h"
|
||||
#include "aisyncclient.h"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "debug.h"
|
||||
|
||||
bool operator==(AISyncKey const& key1, AISyncKey const& key2)
|
||||
{
|
||||
// Test if these keys match based on time.
|
||||
if (std::abs((S32)(key1.mStartFrameCount - key2.mStartFrameCount)) > 1 &&
|
||||
std::abs(key1.mFrameTimer.getStartTime() - key2.mFrameTimer.getStartTime()) >= sSyncKeyExpirationTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Time matches, let the derived classes determine if they also match otherwise.
|
||||
return key1.equals(key2);
|
||||
}
|
||||
|
||||
#ifdef CWDEBUG
|
||||
struct SyncEventSet {
|
||||
synceventset_t mBits;
|
||||
SyncEventSet(synceventset_t bits) : mBits(bits) { }
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, SyncEventSet const& ses)
|
||||
{
|
||||
for (int b = sizeof(ses.mBits) * 8 - 1; b >= 0; --b)
|
||||
{
|
||||
int m = 1 << b;
|
||||
os << ((ses.mBits & m) ? '1' : '0');
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
void print_clients(AISyncServer const* server, AISyncServer::client_list_t const& client_list)
|
||||
{
|
||||
Dout(dc::notice, "Clients of server " << server << ": ");
|
||||
for (AISyncServer::client_list_t::const_iterator iter = client_list.begin(); iter != client_list.end(); ++ iter)
|
||||
{
|
||||
llassert(iter->mClientPtr->mReadyEvents == iter->mReadyEvents);
|
||||
Dout(dc::notice, "-> " << iter->mClientPtr << " : " << SyncEventSet(iter->mReadyEvents));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void AISyncServerMap::register_client(AISyncClient* client, AISyncKey* new_key)
|
||||
{
|
||||
// client must always be a new client that has to be stored somewhere.
|
||||
llassert(client->server() == NULL);
|
||||
// Obviously the client can't be ready for anything when it isn't registered yet.
|
||||
llassert(!client->mReadyEvents);
|
||||
|
||||
// Find if a server with this key already exists.
|
||||
AISyncServer* server = NULL;
|
||||
for (server_list_t::iterator iter = mServers.begin(); iter != mServers.end();)
|
||||
{
|
||||
boost::intrusive_ptr<AISyncServer>& server_ptr = *iter++; // Immediately increment iter because the call to unregister_last_client will erase it.
|
||||
AISyncKey const& server_key(server_ptr->key());
|
||||
if (server_key.is_older_than(*new_key)) // This means that the server key is expired: a new key will never match.
|
||||
{
|
||||
if (server_ptr->never_synced()) // This means that it contains one or zero clients and will never contain more.
|
||||
{
|
||||
// Get rid of this server.
|
||||
server_ptr->unregister_last_client(); // This will cause the server to be deleted, and erased from mServers.
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (*new_key == server_key)
|
||||
{
|
||||
server = server_ptr.get();
|
||||
// mServers stores new servers in strict order of the creation time of the keys,
|
||||
// so once we find a server with a key that is equal, none of the remaining servers
|
||||
// will have expired if they were never synced and we're done with the loop.
|
||||
// Servers that synced might have been added later, but we don't unregister
|
||||
// clients from those anyway because their sync partner might still show up.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (server)
|
||||
{
|
||||
// A server already exists.
|
||||
// Keep the oldest key, unless this new key has a synckeytype_t that is larger!
|
||||
if (new_key->getkeytype() > server->key().getkeytype())
|
||||
{
|
||||
server->swapkey(new_key);
|
||||
}
|
||||
delete new_key;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new server for this client. Transfers the ownership of the key allocation to the server.
|
||||
server = new AISyncServer(new_key);
|
||||
// Add it to mServers, before the last server that is younger then the new key.
|
||||
server_list_t::iterator where = mServers.end(); // Insert the new server before 'where',
|
||||
server_list_t::iterator new_where = where;
|
||||
while (where != mServers.begin()) // unless there exists a server before that
|
||||
{
|
||||
--new_where;
|
||||
if (new_key->getCreationTime() > (*new_where)->key().getCreationTime()) // and the new key is not younger then that,
|
||||
{
|
||||
break;
|
||||
}
|
||||
where = new_where; // then insert it before that element (etc).
|
||||
}
|
||||
// This method causes a single call to intrusive_ptr_add_ref and none to intrusive_ptr_release.
|
||||
server_ptr_t server_ptr = server;
|
||||
mServers.insert(where, server_ptr_t())->swap(server_ptr);
|
||||
}
|
||||
|
||||
// Add the client to the server.
|
||||
server->add(client);
|
||||
}
|
||||
|
||||
#ifdef SYNC_TESTSUITE
|
||||
void AISyncServer::sanity_check(void) const
|
||||
{
|
||||
synceventset_t ready_events = (synceventset_t)-1; // All clients are ready.
|
||||
client_list_t::const_iterator client_iter = mClients.begin();
|
||||
while (client_iter != mClients.end())
|
||||
{
|
||||
ready_events &= client_iter->mReadyEvents;
|
||||
++client_iter;
|
||||
}
|
||||
synceventset_t pending_events = 0; // At least one client is ready.
|
||||
client_iter = mClients.begin();
|
||||
while (client_iter != mClients.end())
|
||||
{
|
||||
pending_events |= client_iter->mReadyEvents;
|
||||
++client_iter;
|
||||
}
|
||||
llassert(ready_events == mReadyEvents);
|
||||
llassert(pending_events == mPendingEvents);
|
||||
}
|
||||
#endif
|
||||
|
||||
void AISyncServer::add(AISyncClient* client)
|
||||
{
|
||||
#ifdef SYNC_TESTSUITE
|
||||
sanity_check();
|
||||
#endif
|
||||
|
||||
// The client can't already be ready when it isn't even added to a server yet.
|
||||
llassert(!client->mReadyEvents);
|
||||
synceventset_t old_ready_events = mReadyEvents;
|
||||
// A new client is not ready for anything.
|
||||
mReadyEvents = 0;
|
||||
// Set mSynchronized if after adding client we'll have more than 1 client (that prevents the
|
||||
// server from being deleted unless all clients are actually destructed or explicitly unregistered).
|
||||
if (!mSynchronized && mClients.size() > 0)
|
||||
{
|
||||
mSynchronized = true;
|
||||
}
|
||||
// Trigger the existing clients to be not-ready anymore (if we were before).
|
||||
trigger(old_ready_events);
|
||||
// Only then add the new client (so that it didn't get not-ready trigger).
|
||||
mClients.push_back(client);
|
||||
client->mServer = this;
|
||||
|
||||
#ifdef SYNC_TESTSUITE
|
||||
sanity_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AISyncServer::remove(AISyncClient* client)
|
||||
{
|
||||
#ifdef SYNC_TESTSUITE
|
||||
sanity_check();
|
||||
#endif
|
||||
|
||||
client_list_t::iterator client_iter = mClients.begin();
|
||||
synceventset_t remaining_ready_events = (synceventset_t)-1; // All clients are ready.
|
||||
synceventset_t remaining_pending_events = 0; // At least one client is ready (waiting for the other clients thus).
|
||||
client_list_t::iterator found_client = mClients.end();
|
||||
while (client_iter != mClients.end())
|
||||
{
|
||||
if (client_iter->mClientPtr == client)
|
||||
{
|
||||
found_client = client_iter;
|
||||
}
|
||||
else
|
||||
{
|
||||
remaining_ready_events &= client_iter->mReadyEvents;
|
||||
remaining_pending_events |= client_iter->mReadyEvents;
|
||||
}
|
||||
++client_iter;
|
||||
}
|
||||
llassert(found_client != mClients.end());
|
||||
// This must be the same as client->mReadyEvents.
|
||||
llassert(found_client->mReadyEvents == client->mReadyEvents);
|
||||
mClients.erase(found_client);
|
||||
synceventset_t old_ready_events = mReadyEvents;
|
||||
mReadyEvents = remaining_ready_events;
|
||||
mPendingEvents = remaining_pending_events;
|
||||
trigger(old_ready_events);
|
||||
client->mServer.reset();
|
||||
client->deregistered();
|
||||
|
||||
#ifdef SYNC_TESTSUITE
|
||||
sanity_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AISyncServer::unregister_last_client(void)
|
||||
{
|
||||
#ifdef SYNC_TESTSUITE
|
||||
sanity_check();
|
||||
#endif
|
||||
|
||||
// This function may only be called for servers with exactly one client that was never (potentially) synchronized.
|
||||
llassert(!mSynchronized && mClients.size() == 1);
|
||||
AISyncClient* client = mClients.begin()->mClientPtr;
|
||||
mClients.clear();
|
||||
client->mServer.reset();
|
||||
llassert(mReadyEvents == client->mReadyEvents);
|
||||
llassert(mPendingEvents == mReadyEvents);
|
||||
// No need to update mReadyEvents/mPendingEvents because the server is going to be deleted,
|
||||
// but inform the client that is no longer has a server.
|
||||
client->deregistered();
|
||||
|
||||
#ifdef SYNC_TESTSUITE
|
||||
sanity_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AISyncServer::trigger(synceventset_t old_ready_events)
|
||||
{
|
||||
// If event 1 changed, informat all clients about it.
|
||||
if (((old_ready_events ^ mReadyEvents) & 1))
|
||||
{
|
||||
for (client_list_t::iterator client_iter = mClients.begin(); client_iter != mClients.end(); ++client_iter)
|
||||
{
|
||||
if ((mReadyEvents & 1))
|
||||
{
|
||||
client_iter->mClientPtr->event1_ready();
|
||||
}
|
||||
else
|
||||
{
|
||||
client_iter->mClientPtr->event1_not_ready();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AISyncServer::ready(synceventset_t events, synceventset_t yesno, AISyncClient* client)
|
||||
{
|
||||
#ifdef SYNC_TESTSUITE
|
||||
sanity_check();
|
||||
#endif
|
||||
|
||||
synceventset_t added_events = events & yesno;
|
||||
synceventset_t removed_events = events & ~yesno;
|
||||
|
||||
// Run over all clients to find the client and calculate the current state.
|
||||
synceventset_t remaining_ready_events = (synceventset_t)-1; // All clients are ready.
|
||||
synceventset_t remaining_pending_events = 0; // At least one client is ready (waiting for the other clients thus).
|
||||
client_list_t::iterator found_client = mClients.end();
|
||||
for (client_list_t::iterator client_iter = mClients.begin(); client_iter != mClients.end(); ++client_iter)
|
||||
{
|
||||
if (client_iter->mClientPtr == client)
|
||||
{
|
||||
found_client = client_iter;
|
||||
}
|
||||
else
|
||||
{
|
||||
remaining_ready_events &= client_iter->mReadyEvents;
|
||||
remaining_pending_events |= client_iter->mReadyEvents;
|
||||
}
|
||||
}
|
||||
|
||||
llassert(mReadyEvents == (remaining_ready_events & found_client->mReadyEvents));
|
||||
llassert(mPendingEvents == (remaining_pending_events | found_client->mReadyEvents));
|
||||
|
||||
found_client->mReadyEvents &= ~removed_events;
|
||||
found_client->mReadyEvents |= added_events;
|
||||
#ifdef SHOW_ASSERT
|
||||
client->mReadyEvents = found_client->mReadyEvents;
|
||||
#endif
|
||||
|
||||
synceventset_t old_ready_events = mReadyEvents;
|
||||
|
||||
mReadyEvents = remaining_ready_events & found_client->mReadyEvents;
|
||||
mPendingEvents = remaining_pending_events | found_client->mReadyEvents;
|
||||
|
||||
trigger(old_ready_events);
|
||||
|
||||
#ifdef SYNC_TESTSUITE
|
||||
sanity_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
void intrusive_ptr_add_ref(AISyncServer* server)
|
||||
{
|
||||
server->mRefCount++;
|
||||
}
|
||||
|
||||
void intrusive_ptr_release(AISyncServer* server)
|
||||
{
|
||||
llassert(server->mRefCount > 0);
|
||||
server->mRefCount--;
|
||||
if (server->mRefCount == 0)
|
||||
{
|
||||
delete server;
|
||||
}
|
||||
else if (server->mRefCount == 1)
|
||||
{
|
||||
// If the the last pointer to this server is in the the AISyncServerMap, then delete that too.
|
||||
AISyncServerMap::instance().remove_server(server);
|
||||
}
|
||||
}
|
||||
|
||||
void AISyncServerMap::remove_server(AISyncServer* server)
|
||||
{
|
||||
for (server_list_t::iterator iter = mServers.begin(); iter != mServers.end(); ++iter)
|
||||
{
|
||||
if (server == iter->get())
|
||||
{
|
||||
mServers.erase(iter); // This causes server to be deleted too.
|
||||
return;
|
||||
}
|
||||
}
|
||||
// The server must be found: this function is only called from intrusive_ptr_release for servers
|
||||
// with just a single server_ptr_t left, which must be the one in mServers (otherwise it wasn't
|
||||
// even registered properly!)
|
||||
llassert(false);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
// SYNC_TESTSUITE
|
||||
//=============================================================================
|
||||
|
||||
#ifdef SYNC_TESTSUITE
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
#include <boost/io/ios_state.hpp>
|
||||
|
||||
//static
|
||||
U32 LLFrameTimer::sFrameCount;
|
||||
|
||||
double innerloop_count = 0;
|
||||
|
||||
double LLFrameTimer::getCurrentTime()
|
||||
{
|
||||
return innerloop_count * 0.001;
|
||||
}
|
||||
|
||||
template<synckeytype_t synckeytype>
|
||||
class TestsuiteKey : public AISyncKey
|
||||
{
|
||||
private:
|
||||
int mIndex;
|
||||
|
||||
public:
|
||||
TestsuiteKey(int index) : mIndex(index) { }
|
||||
|
||||
int getIndex(void) const { return mIndex; }
|
||||
|
||||
// Virtual functions of AISyncKey.
|
||||
public:
|
||||
/*virtual*/ synckeytype_t getkeytype(void) const
|
||||
{
|
||||
// Return a unique identifier for this class, where the low 8 bits represent the syncgroup.
|
||||
return synckeytype;
|
||||
}
|
||||
|
||||
/*virtual*/ bool equals(AISyncKey const& key) const
|
||||
{
|
||||
synckeytype_t const theotherkey = (synckeytype_t)(synckeytype ^ 0x100);
|
||||
switch (key.getkeytype())
|
||||
{
|
||||
case synckeytype:
|
||||
{
|
||||
// The other key is of the same type.
|
||||
TestsuiteKey<synckeytype> const& test_key = static_cast<TestsuiteKey<synckeytype> const&>(key);
|
||||
return (mIndex & 1) == (test_key.mIndex & 1);
|
||||
}
|
||||
case theotherkey:
|
||||
{
|
||||
TestsuiteKey<theotherkey> const& test_key = static_cast<TestsuiteKey<theotherkey> const&>(key);
|
||||
return (mIndex & 2) == (test_key.getIndex() & 2);
|
||||
}
|
||||
default:
|
||||
// The keys must be in the same syncgroup.
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<synckeytype_t synckeytype>
|
||||
class TestsuiteClient : public AISyncClient
|
||||
{
|
||||
// AISyncClient events.
|
||||
protected:
|
||||
/*virtual*/ AISyncKey* createSyncKey(void) const
|
||||
{
|
||||
return new TestsuiteKey<synckeytype>(mIndex);
|
||||
}
|
||||
|
||||
private:
|
||||
int mIndex;
|
||||
bool mRequestedRegistered;
|
||||
synceventset_t mRequestedReady;
|
||||
bool mActualReady1;
|
||||
|
||||
public:
|
||||
TestsuiteClient() : mIndex(-1), mRequestedRegistered(false), mRequestedReady(0), mActualReady1(false) { }
|
||||
~TestsuiteClient() { if (is_registered()) this->ready(mRequestedReady, (synceventset_t)0); }
|
||||
|
||||
void setIndex(int index) { mIndex = index; }
|
||||
|
||||
protected:
|
||||
/*virtual*/ void event1_ready(void)
|
||||
{
|
||||
#ifdef DEBUG_SYNCOUTPUT
|
||||
Dout(dc::notice, "Calling TestsuiteClient<" << synckeytype << ">::event1_ready() (mIndex = " << mIndex << ") of client " << this);
|
||||
#endif
|
||||
llassert(!mActualReady1);
|
||||
mActualReady1 = true;
|
||||
}
|
||||
|
||||
/*virtual*/ void event1_not_ready(void)
|
||||
{
|
||||
#ifdef DEBUG_SYNCOUTPUT
|
||||
Dout(dc::notice, "Calling TestsuiteClient<" << synckeytype << ">::event1_not_ready() (mIndex = " << mIndex << ") of client " << this);
|
||||
#endif
|
||||
llassert(mActualReady1);
|
||||
mActualReady1 = false;
|
||||
}
|
||||
|
||||
// This is called when the server expired and we're the only client on it.
|
||||
/*virtual*/ void deregistered(void)
|
||||
{
|
||||
#ifdef DEBUG_SYNCOUTPUT
|
||||
DoutEntering(dc::notice, "TestsuiteClient<" << synckeytype << ">::deregistered(), with this = " << this);
|
||||
#endif
|
||||
mRequestedRegistered = false;
|
||||
mRequestedReady = 0;
|
||||
mActualReady1 = false;
|
||||
this->mReadyEvents = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
bool is_registered(void) const { return this->server(); }
|
||||
|
||||
public:
|
||||
void change_state(unsigned long r);
|
||||
bool getRequestedRegistered(void) const { return mRequestedRegistered; }
|
||||
synceventset_t getRequestedReady(void) const { return mRequestedReady; }
|
||||
};
|
||||
|
||||
TestsuiteClient<synckeytype_test1a>* client1ap;
|
||||
TestsuiteClient<synckeytype_test1b>* client1bp;
|
||||
TestsuiteClient<synckeytype_test2a>* client2ap;
|
||||
TestsuiteClient<synckeytype_test2b>* client2bp;
|
||||
|
||||
int const number_of_clients_per_syncgroup = 8;
|
||||
|
||||
template<synckeytype_t synckeytype>
|
||||
void TestsuiteClient<synckeytype>::change_state(unsigned long r)
|
||||
{
|
||||
bool change_registered = r & 1;
|
||||
r >>= 1;
|
||||
synceventset_t toggle_events = r & 15;
|
||||
r >>= 4;
|
||||
if (change_registered)
|
||||
{
|
||||
if (mRequestedRegistered && !mRequestedReady)
|
||||
{
|
||||
mRequestedRegistered = false;
|
||||
this->unregister_client();
|
||||
}
|
||||
}
|
||||
else if (toggle_events)
|
||||
{
|
||||
mRequestedReady ^= toggle_events;
|
||||
mRequestedRegistered = true;
|
||||
this->ready(toggle_events, mRequestedReady & toggle_events);
|
||||
}
|
||||
llassert(mRequestedRegistered == is_registered());
|
||||
AISyncServer* server = this->server();
|
||||
if (mRequestedRegistered)
|
||||
{
|
||||
synceventset_t all_ready = synceventset_t(-1);
|
||||
synceventset_t any_ready = 0;
|
||||
int nr = 0;
|
||||
for (int cl = 0; cl < number_of_clients_per_syncgroup; ++cl)
|
||||
{
|
||||
switch ((synckeytype & 0xff))
|
||||
{
|
||||
case syncgroup_test1:
|
||||
{
|
||||
if (client1ap[cl].server() == server)
|
||||
{
|
||||
if (client1ap[cl].getRequestedRegistered())
|
||||
{
|
||||
++nr;
|
||||
all_ready &= client1ap[cl].getRequestedReady();
|
||||
any_ready |= client1ap[cl].getRequestedReady();
|
||||
}
|
||||
}
|
||||
if (client1bp[cl].server() == server)
|
||||
{
|
||||
if (client1bp[cl].getRequestedRegistered())
|
||||
{
|
||||
++nr;
|
||||
all_ready &= client1bp[cl].getRequestedReady();
|
||||
any_ready |= client1bp[cl].getRequestedReady();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case syncgroup_test2:
|
||||
{
|
||||
if (client2ap[cl].server() == server)
|
||||
{
|
||||
if (client2ap[cl].getRequestedRegistered())
|
||||
{
|
||||
++nr;
|
||||
all_ready &= client2ap[cl].getRequestedReady();
|
||||
any_ready |= client2ap[cl].getRequestedReady();
|
||||
}
|
||||
}
|
||||
if (client2bp[cl].server() == server)
|
||||
{
|
||||
if (client2bp[cl].getRequestedRegistered())
|
||||
{
|
||||
++nr;
|
||||
all_ready &= client2bp[cl].getRequestedReady();
|
||||
any_ready |= client2bp[cl].getRequestedReady();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
llassert(nr == server->getClients().size());
|
||||
llassert(!!(all_ready & 1) == mActualReady1);
|
||||
llassert(this->server()->events_with_all_clients_ready() == all_ready);
|
||||
llassert(this->server()->events_with_at_least_one_client_ready() == any_ready);
|
||||
llassert(nr == 0 || (any_ready & all_ready) == all_ready);
|
||||
}
|
||||
llassert(mRequestedReady == this->mReadyEvents);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Debug(libcw_do.on());
|
||||
Debug(dc::notice.on());
|
||||
Debug(libcw_do.set_ostream(&std::cout));
|
||||
Debug(list_channels_on(libcw_do));
|
||||
|
||||
unsigned short seed16v[3] = { 0x1234, 0xfedc, 0x7091 };
|
||||
|
||||
for (int k = 0;; ++k)
|
||||
{
|
||||
std::cout << "Loop: " << k << "; SEED: " << std::hex << seed16v[0] << ", " << seed16v[1] << ", " << seed16v[2] << std::dec << std::endl;
|
||||
++LLFrameTimer::sFrameCount;
|
||||
|
||||
seed48(seed16v);
|
||||
seed16v[0] = lrand48() & 0xffff;
|
||||
seed16v[1] = lrand48() & 0xffff;
|
||||
seed16v[2] = lrand48() & 0xffff;
|
||||
|
||||
TestsuiteClient<synckeytype_test1a> client1a[number_of_clients_per_syncgroup];
|
||||
TestsuiteClient<synckeytype_test1b> client1b[number_of_clients_per_syncgroup];
|
||||
TestsuiteClient<synckeytype_test2a> client2a[number_of_clients_per_syncgroup];
|
||||
TestsuiteClient<synckeytype_test2b> client2b[number_of_clients_per_syncgroup];
|
||||
client1ap = client1a;
|
||||
client1bp = client1b;
|
||||
client2ap = client2a;
|
||||
client2bp = client2b;
|
||||
|
||||
for (int i = 0; i < number_of_clients_per_syncgroup; ++i)
|
||||
{
|
||||
client1a[i].setIndex(i);
|
||||
client1b[i].setIndex(i);
|
||||
client2a[i].setIndex(i);
|
||||
client2b[i].setIndex(i);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 1000000; ++j)
|
||||
{
|
||||
innerloop_count += 1;
|
||||
|
||||
#ifdef DEBUG_SYNCOUTPUT
|
||||
Dout(dc::notice, "Innerloop: " << j);
|
||||
#endif
|
||||
unsigned long r = lrand48();
|
||||
synckeytype_t keytype = (r & 1) ? ((r & 2) ? synckeytype_test1a : synckeytype_test1b) : ((r & 2) ? synckeytype_test2a : synckeytype_test2b);
|
||||
r >>= 2;
|
||||
int cl = (r & 255) % number_of_clients_per_syncgroup;
|
||||
r >>= 8;
|
||||
switch (keytype)
|
||||
{
|
||||
case synckeytype_test1a:
|
||||
client1a[cl].change_state(r);
|
||||
break;
|
||||
case synckeytype_test1b:
|
||||
client1b[cl].change_state(r);
|
||||
break;
|
||||
case synckeytype_test2a:
|
||||
client2a[cl].change_state(r);
|
||||
break;
|
||||
case synckeytype_test2b:
|
||||
client2b[cl].change_state(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
304
indra/llcommon/aisyncclient.h
Normal file
304
indra/llcommon/aisyncclient.h
Normal file
@@ -0,0 +1,304 @@
|
||||
/**
|
||||
* @file aisyncclient.h
|
||||
* @brief Declaration of AISyncClient.
|
||||
*
|
||||
* Copyright (c) 2013, Aleric Inglewood.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution.
|
||||
*
|
||||
* CHANGELOG
|
||||
* and additional copyright holders.
|
||||
*
|
||||
* 12/12/2013
|
||||
* Initial version, written by Aleric Inglewood @ SL
|
||||
*/
|
||||
|
||||
#ifndef AI_SYNC_CLIENT_H
|
||||
#define AI_SYNC_CLIENT_H
|
||||
|
||||
#ifdef SYNC_TESTSUITE
|
||||
/*
|
||||
* To compile the testsuite, run:
|
||||
*
|
||||
* cd indra/llcommon
|
||||
* g++ -O3 -DCWDEBUG -DSYNC_TESTSUITE -I. -I../cwdebug aisyncclient.cpp -lcwd
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cassert>
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t S32;
|
||||
typedef uint64_t U64;
|
||||
typedef float F32;
|
||||
typedef double F64;
|
||||
#define LL_COMMON_API
|
||||
#define SHOW_ASSERT
|
||||
#define ASSERT_ONLY_COMMA(...) , __VA_ARGS__
|
||||
#define llassert assert
|
||||
|
||||
struct LLFrameTimer
|
||||
{
|
||||
double mStartTime;
|
||||
double mExpiry;
|
||||
static double getCurrentTime(void);
|
||||
static U32 sFrameCount;
|
||||
static U32 getFrameCount() { return sFrameCount; }
|
||||
F64 getStartTime() const { return mStartTime; }
|
||||
void reset(double expiration) { mStartTime = getCurrentTime(); mExpiry = mStartTime + expiration; }
|
||||
bool hasExpired(void) const { return getCurrentTime() > mExpiry; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LLSingleton
|
||||
{
|
||||
static T sInstance;
|
||||
static T& instance(void) { return sInstance; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T LLSingleton<T>::sInstance;
|
||||
|
||||
#else // !SYNC_TESTSUITE
|
||||
#include "llsingleton.h"
|
||||
#include "llframetimer.h"
|
||||
#endif
|
||||
#include <list>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Keys with a different syncgroup are never equal (so they are never synchronized).
|
||||
enum syncgroups
|
||||
{
|
||||
#ifdef SYNC_TESTSUITE
|
||||
syncgroup_test1,
|
||||
syncgroup_test2,
|
||||
#else
|
||||
syncgroup_motions, // Syncgroup used for animations.
|
||||
#endif
|
||||
syncgroup_size
|
||||
};
|
||||
|
||||
// Each key type must return a unique identifier that exists of its syncgroup (the least significant 8 bit) plus a few bit to make it unique (bit 9 and higher).
|
||||
enum synckeytype_t
|
||||
{
|
||||
#ifdef SYNC_TESTSUITE
|
||||
synckeytype_test1a = 0x000 + syncgroup_test1,
|
||||
synckeytype_test1b = 0x100 + syncgroup_test1,
|
||||
synckeytype_test2a = 0x000 + syncgroup_test2,
|
||||
synckeytype_test2b = 0x100 + syncgroup_test2,
|
||||
#else
|
||||
synckeytype_motion = syncgroup_motions // There is currently only one key type in the syncgroup_motions group: AISyncKeyMotion.
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef U32 synceventset_t; // A mask where each bit represents a ready state.
|
||||
|
||||
static F32 const sSyncKeyExpirationTime = 0.25; // In seconds.
|
||||
|
||||
class LL_COMMON_API AISyncKey
|
||||
{
|
||||
private:
|
||||
LLFrameTimer mFrameTimer; // This timer is started at the moment the sync key is created.
|
||||
U32 mStartFrameCount; // The frame count at which the timer was started.
|
||||
|
||||
public:
|
||||
// Constructor.
|
||||
AISyncKey(AISyncKey const* from_key) : mStartFrameCount(from_key ? from_key->mStartFrameCount : LLFrameTimer::getFrameCount())
|
||||
{
|
||||
if (from_key)
|
||||
{
|
||||
mFrameTimer.copy(from_key->mFrameTimer);
|
||||
}
|
||||
else
|
||||
{
|
||||
mFrameTimer.reset(sSyncKeyExpirationTime);
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
virtual ~AISyncKey() { }
|
||||
|
||||
// Return true if this key expired.
|
||||
bool expired(void) const
|
||||
{
|
||||
// The key has expired when sSyncKeyExpirationTime seconds have elapsed AND at least two frames have passed.
|
||||
return mFrameTimer.getFrameCount() > mStartFrameCount + 1 && mFrameTimer.hasExpired();
|
||||
}
|
||||
|
||||
// Returns true if this object and key would not compare equal based on time because this object is too old.
|
||||
bool is_older_than(AISyncKey const& key) const
|
||||
{
|
||||
return key.mStartFrameCount > mStartFrameCount + 1 && key.mFrameTimer.getStartTime() > mFrameTimer.getStartTime() + sSyncKeyExpirationTime;
|
||||
}
|
||||
|
||||
// Return the creation time of this key (in number of seconds since application start).
|
||||
F64 getCreationTime(void) const { return mFrameTimer.getStartTime(); }
|
||||
|
||||
// Returns true if the two keys match, meaning that they should be synchronized.
|
||||
friend bool operator==(AISyncKey const& key1, AISyncKey const& key2);
|
||||
|
||||
// Returns an ID that uniquely identifies the derived type.
|
||||
// Currently the only derived type is AISyncKeyMotion with ID synckeytype_motion.
|
||||
virtual synckeytype_t getkeytype(void) const = 0;
|
||||
|
||||
// Returns true if the data in the derived objects match, meaning that they should be synchronized.
|
||||
virtual bool equals(AISyncKey const& key) const = 0;
|
||||
};
|
||||
|
||||
// Forward declaration.
|
||||
class AISyncClient;
|
||||
class AISyncServer;
|
||||
LL_COMMON_API extern void intrusive_ptr_add_ref(AISyncServer* server);
|
||||
LL_COMMON_API extern void intrusive_ptr_release(AISyncServer* server);
|
||||
|
||||
struct LL_COMMON_API AISyncClientData
|
||||
{
|
||||
AISyncClient* mClientPtr;
|
||||
synceventset_t mReadyEvents;
|
||||
|
||||
AISyncClientData(AISyncClient* client) : mClientPtr(client), mReadyEvents(0) { }
|
||||
};
|
||||
|
||||
class LL_COMMON_API AISyncServer
|
||||
{
|
||||
public:
|
||||
typedef std::list<AISyncClientData> client_list_t;
|
||||
|
||||
private:
|
||||
int mRefCount; // Number of boost::intrusive_ptr objects pointing to this object.
|
||||
AISyncKey* mKey; // The key of the first client that was added.
|
||||
client_list_t mClients; // A list with pointers to all registered clients.
|
||||
bool mSynchronized; // Set when a server gets more than one client, and not reset anymore after that.
|
||||
synceventset_t mReadyEvents; // 0xFFFFFFFF bitwise-AND-ed with all clients.
|
||||
synceventset_t mPendingEvents; // The bitwise-OR of all clients.
|
||||
|
||||
public:
|
||||
AISyncServer(AISyncKey* key) : mRefCount(0), mKey(key), mSynchronized(false), mReadyEvents((synceventset_t)-1), mPendingEvents(0) { }
|
||||
~AISyncServer() { delete mKey; }
|
||||
|
||||
// Add a new client to this server.
|
||||
void add(AISyncClient* client);
|
||||
|
||||
// Remove a client from this server.
|
||||
void remove(AISyncClient* client);
|
||||
|
||||
// Return the key associated to this server (which is the key produced by the first client of the largest synckeytype_t that was added).
|
||||
AISyncKey const& key(void) const { return *mKey; }
|
||||
// Replace they key with another key (of larger synckeytype_t).
|
||||
void swapkey(AISyncKey*& key_ptr) { AISyncKey* tmp = key_ptr; key_ptr = mKey; mKey = tmp; }
|
||||
|
||||
// Returns true if this server never had more than one client.
|
||||
bool never_synced(void) const { return !mSynchronized; }
|
||||
|
||||
// Set readiness of all events at once.
|
||||
void ready(synceventset_t events, synceventset_t yesno, AISyncClient* client);
|
||||
|
||||
// Unregister the (only) client because it's own its own and will never need synchronization.
|
||||
void unregister_last_client(void);
|
||||
|
||||
// Return the events that all clients for.
|
||||
synceventset_t events_with_all_clients_ready(void) const { return mReadyEvents; }
|
||||
|
||||
// Return events that at least one client is ready for.
|
||||
synceventset_t events_with_at_least_one_client_ready(void) const { return mPendingEvents; }
|
||||
|
||||
// Return a list of all registered clients.
|
||||
client_list_t const& getClients(void) const { return mClients; }
|
||||
|
||||
private:
|
||||
// Call event1_ready() or event1_not_ready() on all clients if the least significant bit of mReadyEvents changed.
|
||||
void trigger(synceventset_t old_ready_events);
|
||||
|
||||
#ifdef SYNC_TESTSUITE
|
||||
void sanity_check(void) const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend LL_COMMON_API void intrusive_ptr_add_ref(AISyncServer* server);
|
||||
friend LL_COMMON_API void intrusive_ptr_release(AISyncServer* server);
|
||||
};
|
||||
|
||||
class LL_COMMON_API AISyncServerMap : public LLSingleton<AISyncServerMap>
|
||||
{
|
||||
public:
|
||||
typedef boost::intrusive_ptr<AISyncServer> server_ptr_t; // The type of a (stored) pointer to the server objects.
|
||||
typedef std::list<server_ptr_t> server_list_t; // The type of the list with pointers to the server objects.
|
||||
|
||||
private:
|
||||
server_list_t mServers; // A list with pointers to all server objects.
|
||||
|
||||
public:
|
||||
// Find or create a server object that the client belongs to and store the client in it.
|
||||
// If a new server is created, it is stored in mServers.
|
||||
void register_client(AISyncClient* client, AISyncKey* new_key);
|
||||
|
||||
private:
|
||||
friend LL_COMMON_API void intrusive_ptr_release(AISyncServer* server);
|
||||
// Remove a server from the map, only called by intrusive_ptr_release when there is one pointer left;
|
||||
// therefore, the server should not have any clients.
|
||||
void remove_server(AISyncServer* server);
|
||||
};
|
||||
|
||||
class LL_COMMON_API AISyncClient
|
||||
{
|
||||
private:
|
||||
friend class AISyncServer;
|
||||
boost::intrusive_ptr<AISyncServer> mServer; // The server this client was registered with, or NULL when unregistered.
|
||||
|
||||
public:
|
||||
#ifdef SHOW_ASSERT
|
||||
synceventset_t mReadyEvents;
|
||||
AISyncClient(void) : mReadyEvents(0) { }
|
||||
#endif
|
||||
virtual ~AISyncClient() { llassert(!mServer); /* If this fails then you need to add unregister_client() to the top of the destructor of the derived class that implements deregistered(). */ }
|
||||
virtual AISyncKey* createSyncKey(AISyncKey const* from_key = NULL) const = 0;
|
||||
|
||||
virtual void event1_ready(void) = 0;
|
||||
virtual void event1_not_ready(void) = 0;
|
||||
|
||||
// Only client. Client was forcefully deregistered from expired server because it was the only client.
|
||||
virtual void deregistered(void)
|
||||
{
|
||||
#ifdef SHOW_ASSERT
|
||||
mReadyEvents = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
AISyncServer* server(void) const { return mServer.get(); }
|
||||
|
||||
// Add this client to a server with matching sync key. Optionally the server is first created.
|
||||
void register_client(void) { AISyncServerMap::instance().register_client(this, createSyncKey()); }
|
||||
|
||||
// Remove this client from its server, if any.
|
||||
void unregister_client(void) { if (mServer) mServer->remove(this); }
|
||||
|
||||
// Call 'ready' when you are ready (or not) to get a call to start().
|
||||
// Returns true if that call was made (immediately), otherwise it may happen later.
|
||||
|
||||
// Set readiness of all events at once.
|
||||
void ready(synceventset_t events, synceventset_t yesno)
|
||||
{
|
||||
if (!mServer)
|
||||
{
|
||||
register_client();
|
||||
}
|
||||
mServer->ready(events, yesno, this);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
25
indra/llcommon/fix_macros.h
Normal file
25
indra/llcommon/fix_macros.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @file fix_macros.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2012-11-16
|
||||
* @brief The Mac system headers seem to #define macros with obnoxiously
|
||||
* generic names, preventing any library from using those names. We've
|
||||
* had to fix these in so many places that it's worth making a header
|
||||
* file to handle it.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Copyright (c) 2012, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// DON'T use an #include guard: every time we encounter this header, #undef
|
||||
// these macros all over again.
|
||||
|
||||
// who injects MACROS with such generic names?! Grr.
|
||||
#ifdef equivalent
|
||||
#undef equivalent
|
||||
#endif
|
||||
|
||||
#ifdef check
|
||||
#undef check
|
||||
#endif
|
||||
@@ -47,6 +47,10 @@ public:
|
||||
// Create an LLFrameTimer and start it. After creation it is running and in the state expired (hasExpired will return true).
|
||||
LLFrameTimer(void) : mExpiry(0), mRunning(true), mPaused(false) { if (!sGlobalMutex) global_initialization(); setAge(0.0); }
|
||||
|
||||
//<singu>
|
||||
void copy(LLFrameTimer const& timer) { mStartTime = timer.mStartTime; mExpiry = timer.mExpiry; mRunning = timer.mRunning; mPaused = timer.mPaused; }
|
||||
//</singu>
|
||||
|
||||
// Atomic reads of static variables.
|
||||
|
||||
// Return the number of seconds since the start of the application.
|
||||
@@ -142,6 +146,9 @@ public:
|
||||
bool hasExpired() const { return getElapsedSeconds() >= mExpiry; }
|
||||
F32 getElapsedTimeF32() const { llassert(mRunning); return mPaused ? (F32)mStartTime : (F32)(getElapsedSeconds() - mStartTime); }
|
||||
bool getStarted() const { return mRunning; }
|
||||
//<singu>
|
||||
F64 getStartTime() const { llassert(!mPaused); return mStartTime; }
|
||||
//</singu>
|
||||
|
||||
// return the seconds since epoch when this timer will expire.
|
||||
F64 expiresAt() const;
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
/**
|
||||
* @file llindraconfigfile.cpp
|
||||
*
|
||||
*
|
||||
* This class is an LLLiveFile that has config info for indra
|
||||
* Currently only whether it's blacklisted
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2007-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llindraconfigfile.h"
|
||||
|
||||
#include "llfile.h"
|
||||
#include "llsd.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llframetimer.h"
|
||||
|
||||
static std::string sConfigDir = "";
|
||||
static const char indraConfigFileName[] = "indra.xml";
|
||||
|
||||
|
||||
LLIndraConfigFile::LLIndraConfigFile()
|
||||
: LLLiveFile(filename()),
|
||||
mConfig(LLSD())
|
||||
{
|
||||
}
|
||||
|
||||
//static
|
||||
void LLIndraConfigFile::initClass(const std::string& config_dir)
|
||||
{
|
||||
sConfigDir = config_dir;
|
||||
llinfos << "LLIndraConfigFile::initClass config dir "
|
||||
<< config_dir << "/" << indraConfigFileName << llendl;
|
||||
}
|
||||
|
||||
LLSD LLIndraConfigFile::getConfig(const std::string& config_name)
|
||||
{
|
||||
if (sConfigDir.empty())
|
||||
{
|
||||
llerrs << "LLIndraConfigFile::initClass() not called" << llendl;
|
||||
}
|
||||
|
||||
LLFrameTimer::updateFrameTime();
|
||||
|
||||
static LLIndraConfigFile the_file;
|
||||
the_file.checkAndReload();
|
||||
|
||||
return the_file.mConfig[config_name];
|
||||
}
|
||||
|
||||
std::string LLIndraConfigFile::filename()
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
|
||||
ostr << sConfigDir
|
||||
<< "/" << indraConfigFileName;
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
bool LLIndraConfigFile::loadFile()
|
||||
{
|
||||
llinfos << "LLIndraConfigFile::loadFile: reading from "
|
||||
<< filename() << llendl;
|
||||
|
||||
LLSD config;
|
||||
|
||||
{
|
||||
llifstream file(filename());
|
||||
if (file.is_open())
|
||||
{
|
||||
LLSDSerialize::fromXML(config, file);
|
||||
}
|
||||
|
||||
if (config.isUndefined())
|
||||
{
|
||||
llinfos << "LLIndraConfigFile::loadFile: file missing, ill-formed,"
|
||||
" or simply undefined; not changing the blacklist" << llendl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.isMap())
|
||||
{
|
||||
mConfig = config;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "LLIndraConfigFile: " << indraConfigFileName << " expects a map; wrong format" << llendl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* @file llindraconfigfile.h
|
||||
* @brief manages configuration file for indra.xml
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2007-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLINDRACONFIGFILE_H
|
||||
#define LL_LLINDRACONFIGFILE_H
|
||||
|
||||
#include "linden_common.h"
|
||||
#include <string>
|
||||
|
||||
#include "lllivefile.h"
|
||||
#include "llsd.h"
|
||||
|
||||
|
||||
// To use, call LLIndraConfigFile::initClass(config_dir);
|
||||
// Then whenever getConfig is called, it will check and reload automatically
|
||||
|
||||
class LLIndraConfigFile : public LLLiveFile
|
||||
{
|
||||
public:
|
||||
LLIndraConfigFile();
|
||||
static void initClass(const std::string& config_dir);
|
||||
static LLSD getConfig(const std::string& config_name);
|
||||
|
||||
private:
|
||||
static std::string filename();
|
||||
|
||||
protected:
|
||||
/* virtual */ bool loadFile();
|
||||
LLSD mConfig;
|
||||
};
|
||||
|
||||
#endif //LL_LLINDRACONFIGFILE_H
|
||||
@@ -239,14 +239,14 @@ inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_ty
|
||||
//
|
||||
//Singu note: This has been generalized to support a broader range of sequence containers
|
||||
template <typename T>
|
||||
inline typename T::iterator vector_replace_with_last(T& invec, typename T::iterator& iter)
|
||||
inline typename T::iterator vector_replace_with_last(T& invec, typename T::iterator iter)
|
||||
{
|
||||
typename T::iterator last = invec.end(); --last;
|
||||
typename T::iterator last = invec.end();
|
||||
if (iter == invec.end())
|
||||
{
|
||||
return iter;
|
||||
}
|
||||
else if (iter == last)
|
||||
else if (iter == --last)
|
||||
{
|
||||
invec.pop_back();
|
||||
return invec.end();
|
||||
|
||||
@@ -1288,7 +1288,7 @@ public:
|
||||
LL_CONT << "slowest framerate for last " << int(prevSize * MEM_INFO_THROTTLE)
|
||||
<< " seconds ";
|
||||
}
|
||||
LL_CONT << std::fixed << std::setprecision(1) << framerate << '\n'
|
||||
LL_CONT << std::fixed << std::setprecision(1) << framerate << std::setprecision(6) << '\n'
|
||||
<< LLMemoryInfo() << LL_ENDL;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
const S32 LL_VERSION_MAJOR = 1;
|
||||
const S32 LL_VERSION_MINOR = 8;
|
||||
const S32 LL_VERSION_PATCH = 5;
|
||||
const S32 LL_VERSION_PATCH = 6;
|
||||
const S32 LL_VERSION_BUILD = ${vBUILD};
|
||||
|
||||
const char * const LL_CHANNEL = "${VIEWER_CHANNEL}";
|
||||
|
||||
@@ -118,16 +118,6 @@ enum EAddPosition
|
||||
ADD_BOTTOM
|
||||
};
|
||||
|
||||
enum LLGroupChange
|
||||
{
|
||||
GC_PROPERTIES,
|
||||
GC_MEMBER_DATA,
|
||||
GC_ROLE_DATA,
|
||||
GC_ROLE_MEMBER_DATA,
|
||||
GC_TITLES,
|
||||
GC_ALL
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// DEPRECATED - create new, more specific files for shared enums/constants
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -178,7 +178,7 @@ BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream)
|
||||
while(input_stream.good())
|
||||
{
|
||||
input_stream.getline(buffer, MAX_STRING);
|
||||
sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */
|
||||
if (sscanf(buffer, " %254s %254s", keyword, valuestr) < 1) continue;
|
||||
if(0 == strcmp("{",keyword))
|
||||
{
|
||||
continue;
|
||||
@@ -268,7 +268,7 @@ void LLInventoryObject::updateServer(BOOL) const
|
||||
llwarns << "LLInventoryObject::updateServer() called. Doesn't do anything." << llendl;
|
||||
}
|
||||
|
||||
inline
|
||||
// inline
|
||||
void LLInventoryObject::correctInventoryName(std::string& name)
|
||||
{
|
||||
LLStringUtil::replaceNonstandardASCII(name, ' ');
|
||||
@@ -610,7 +610,7 @@ BOOL LLInventoryItem::importFile(LLFILE* fp)
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
|
||||
sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */
|
||||
if (sscanf(buffer, " %254s %254s", keyword, valuestr) < 1) continue;
|
||||
if(0 == strcmp("{",keyword))
|
||||
{
|
||||
continue;
|
||||
@@ -813,10 +813,10 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream)
|
||||
while(success && input_stream.good())
|
||||
{
|
||||
input_stream.getline(buffer, MAX_STRING);
|
||||
sscanf( /* Flawfinder: ignore */
|
||||
if (sscanf(
|
||||
buffer,
|
||||
" %254s %254s",
|
||||
keyword, valuestr);
|
||||
keyword, valuestr) < 1) continue;
|
||||
if(0 == strcmp("{",keyword))
|
||||
{
|
||||
continue;
|
||||
@@ -1169,7 +1169,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd)
|
||||
// Because WT_UNKNOWN now has locally a special meaning, make sure we don't receive it from the server.
|
||||
if (wt == WT_UNKNOWN)
|
||||
{
|
||||
llwarns << "Received inventory item with wearable type WT_UNKNOWN from server! You should upgrade your viewer." << llendl;
|
||||
lldebugs << "Received inventory item with wearable type WT_UNKNOWN from server!" << llendl;
|
||||
// Change this new wearable type to WT_COUNT, as if when we had not inserted WT_UNKNOWN locally.
|
||||
mFlags += 1;
|
||||
wt = WT_COUNT;
|
||||
@@ -1489,10 +1489,10 @@ BOOL LLInventoryCategory::importFile(LLFILE* fp)
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
|
||||
sscanf( /* Flawfinder: ignore */
|
||||
if (sscanf(
|
||||
buffer,
|
||||
" %254s %254s",
|
||||
keyword, valuestr);
|
||||
keyword, valuestr) < 1) continue;
|
||||
if(0 == strcmp("{",keyword))
|
||||
{
|
||||
continue;
|
||||
@@ -1568,10 +1568,10 @@ BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream)
|
||||
while(input_stream.good())
|
||||
{
|
||||
input_stream.getline(buffer, MAX_STRING);
|
||||
sscanf( /* Flawfinder: ignore */
|
||||
if (sscanf(
|
||||
buffer,
|
||||
" %254s %254s",
|
||||
keyword, valuestr);
|
||||
keyword, valuestr) < 1) continue;
|
||||
if(0 == strcmp("{",keyword))
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -84,9 +84,13 @@ public:
|
||||
void setParent(const LLUUID& new_parent);
|
||||
void setType(LLAssetType::EType type);
|
||||
|
||||
private:
|
||||
// [RLVa:KB] - Checked: 2014-01-07 (RLVa-1.4.10)
|
||||
// in place correction for inventory name string
|
||||
void correctInventoryName(std::string& name);
|
||||
static void correctInventoryName(std::string& name);
|
||||
// [/RLVa:KB]
|
||||
private:
|
||||
// // in place correction for inventory name string
|
||||
// void correctInventoryName(std::string& name);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// File Support
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file camera.h
|
||||
* @brief Legacy wrapper header.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file coordframe.h
|
||||
* @brief Legacy wrapper header.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,36 +2,28 @@
|
||||
* @file llbbox.cpp
|
||||
* @brief General purpose bounding box class (Not axis aligned)
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2010, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlife.com/developers/opensource/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlife.com/developers/opensource/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
// self include
|
||||
|
||||
@@ -2,36 +2,28 @@
|
||||
* @file llbbox.h
|
||||
* @brief General purpose bounding box class
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2010, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlife.com/developers/opensource/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlife.com/developers/opensource/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LL_BBOX_H
|
||||
#define LL_BBOX_H
|
||||
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llbboxlocal.cpp
|
||||
* @brief General purpose bounding box class (Not axis aligned).
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llbboxlocal.h
|
||||
* @brief General purpose bounding box class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llcamera.cpp
|
||||
* @brief Implementation of the LLCamera class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -189,8 +183,30 @@ static const LLVector4a sFrustumScaler[] =
|
||||
LLVector4a( 1, 1, 1) // 8 entries
|
||||
};
|
||||
|
||||
S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius)
|
||||
bool LLCamera::isChanged()
|
||||
{
|
||||
bool changed = false;
|
||||
for (U32 i = 0; i < mPlaneCount; i++)
|
||||
{
|
||||
U8 mask = mPlaneMask[i];
|
||||
if (mask != 0xff && !changed)
|
||||
{
|
||||
changed = !mAgentPlanes[i].equal(mLastAgentPlanes[i]);
|
||||
}
|
||||
mLastAgentPlanes[i].set(mAgentPlanes[i]);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius, const LLPlane* planes)
|
||||
{
|
||||
if(!planes)
|
||||
{
|
||||
//use agent space
|
||||
planes = mAgentPlanes;
|
||||
}
|
||||
|
||||
U8 mask = 0;
|
||||
bool result = false;
|
||||
LLVector4a rscale, maxp, minp;
|
||||
@@ -201,7 +217,7 @@ S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius)
|
||||
mask = mPlaneMask[i];
|
||||
if (mask < PLANE_MASK_NUM)
|
||||
{
|
||||
const LLPlane& p(mAgentPlanes[i]);
|
||||
const LLPlane& p(planes[i]);
|
||||
p.getAt<3>(d);
|
||||
rscale.setMul(radius, sFrustumScaler[mask]);
|
||||
minp.setSub(center, rscale);
|
||||
@@ -222,9 +238,21 @@ S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius)
|
||||
return result?1:2;
|
||||
}
|
||||
|
||||
|
||||
S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius)
|
||||
//exactly same as the function AABBInFrustum(...)
|
||||
//except uses mRegionPlanes instead of mAgentPlanes.
|
||||
S32 LLCamera::AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius)
|
||||
{
|
||||
return AABBInFrustum(center, radius, mRegionPlanes);
|
||||
}
|
||||
|
||||
S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes)
|
||||
{
|
||||
if(!planes)
|
||||
{
|
||||
//use agent space
|
||||
planes = mAgentPlanes;
|
||||
}
|
||||
|
||||
U8 mask = 0;
|
||||
bool result = false;
|
||||
LLVector4a rscale, maxp, minp;
|
||||
@@ -235,7 +263,7 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a&
|
||||
mask = mPlaneMask[i];
|
||||
if ((i != 5) && (mask < PLANE_MASK_NUM))
|
||||
{
|
||||
const LLPlane& p(mAgentPlanes[i]);
|
||||
const LLPlane& p(planes[i]);
|
||||
p.getAt<3>(d);
|
||||
rscale.setMul(radius, sFrustumScaler[mask]);
|
||||
minp.setSub(center, rscale);
|
||||
@@ -256,6 +284,13 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a&
|
||||
return result?1:2;
|
||||
}
|
||||
|
||||
//exactly same as the function AABBInFrustumNoFarClip(...)
|
||||
//except uses mRegionPlanes instead of mAgentPlanes.
|
||||
S32 LLCamera::AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius)
|
||||
{
|
||||
return AABBInFrustumNoFarClip(center, radius, mRegionPlanes);
|
||||
}
|
||||
|
||||
int LLCamera::sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius)
|
||||
{
|
||||
LLVector3 dist = sphere_center-mFrustCenter;
|
||||
@@ -592,6 +627,47 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
|
||||
}
|
||||
}
|
||||
|
||||
//calculate regional planes from mAgentPlanes.
|
||||
//vector "shift" is the vector of the region origin in the agent space.
|
||||
void LLCamera::calcRegionFrustumPlanes(const LLVector3& shift, F32 far_clip_distance)
|
||||
{
|
||||
F32 far_w;
|
||||
{
|
||||
LLVector3 p = getOrigin();
|
||||
LLVector3 n(mAgentPlanes[5][0], mAgentPlanes[5][1], mAgentPlanes[5][2]);
|
||||
F32 dd = n * p;
|
||||
if(dd + mAgentPlanes[5][3] < 0) //signed distance
|
||||
{
|
||||
far_w = -far_clip_distance - dd;
|
||||
}
|
||||
else
|
||||
{
|
||||
far_w = far_clip_distance - dd;
|
||||
}
|
||||
far_w += n * shift;
|
||||
}
|
||||
|
||||
F32 d;
|
||||
LLVector3 n;
|
||||
for(S32 i = 0 ; i < 7; i++)
|
||||
{
|
||||
if (mPlaneMask[i] != 0xff)
|
||||
{
|
||||
n.setVec(mAgentPlanes[i][0], mAgentPlanes[i][1], mAgentPlanes[i][2]);
|
||||
|
||||
if(i != 5)
|
||||
{
|
||||
d = mAgentPlanes[i][3] + n * shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
d = far_w;
|
||||
}
|
||||
mRegionPlanes[i].setVec(n, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLCamera::calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom)
|
||||
{
|
||||
LLVector3 a, b, c;
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llcamera.h
|
||||
* @brief Header file for the LLCamera class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -55,7 +49,7 @@ const F32 MIN_FAR_PLANE = 0.2f;
|
||||
|
||||
// Min/Max FOV values for square views. Call getMin/MaxView to get extremes based on current aspect ratio.
|
||||
static const F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD;
|
||||
static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
|
||||
static const F32 MAX_FIELD_OF_VIEW = 320.f * DEG_TO_RAD;
|
||||
|
||||
// An LLCamera is an LLCoorFrame with a view frustum.
|
||||
// This means that it has several methods for moving it around
|
||||
@@ -128,6 +122,8 @@ public:
|
||||
|
||||
private:
|
||||
LL_ALIGN_16(LLPlane mAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
|
||||
LL_ALIGN_16(LLPlane mRegionPlanes[AGENT_PLANE_USER_CLIP_NUM]); //frustum planes in a local region space, derived from mAgentPlanes
|
||||
LL_ALIGN_16(LLPlane mLastAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]);
|
||||
U8 mPlaneMask[PLANE_MASK_NUM]; // 8 for alignment
|
||||
|
||||
F32 mView; // angle between top and bottom frustum planes in radians.
|
||||
@@ -156,6 +152,7 @@ public:
|
||||
LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
|
||||
virtual ~LLCamera();
|
||||
|
||||
bool isChanged(); //check if mAgentPlanes changed since last frame.
|
||||
|
||||
void setUserClipPlane(const LLPlane& plane);
|
||||
void disableUserClipPlane();
|
||||
@@ -197,6 +194,7 @@ public:
|
||||
// Return number of bytes copied.
|
||||
size_t readFrustumFromBuffer(const char *buffer);
|
||||
void calcAgentFrustumPlanes(LLVector3* frust);
|
||||
void calcRegionFrustumPlanes(const LLVector3& shift, F32 far_clip_distance); //calculate regional planes from mAgentPlanes.
|
||||
void ignoreAgentFrustumPlane(S32 idx);
|
||||
|
||||
// Returns 1 if partly in, 2 if fully in.
|
||||
@@ -205,8 +203,10 @@ public:
|
||||
S32 sphereInFrustum(const LLVector3 ¢er, const F32 radius) const;
|
||||
S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); }
|
||||
S32 sphereInFrustumFull(const LLVector3 ¢er, const F32 radius) const { return sphereInFrustum(center, radius); }
|
||||
S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius);
|
||||
S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius);
|
||||
S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL);
|
||||
S32 AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius);
|
||||
S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL);
|
||||
S32 AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius);
|
||||
|
||||
//does a quick 'n dirty sphere-sphere check
|
||||
S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius);
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llcoordframe.cpp
|
||||
* @brief LLCoordFrame class implementation.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llcoordframe.h
|
||||
* @brief LLCoordFrame class header file.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,31 +1,25 @@
|
||||
/**
|
||||
* @file llinterp.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,31 +3,25 @@
|
||||
* @author Andrew Meadows
|
||||
* @brief Simple line class that can compute nearest approach between two lines
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2006-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,31 +4,25 @@
|
||||
* @author Andrew Meadows
|
||||
* @brief Simple line for computing nearest approach between two infinite lines
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2006-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include "lldefs.h"
|
||||
//#include "llstl.h" // *TODO: Remove when LLString is gone
|
||||
//#include "llstring.h" // *TODO: Remove when LLString is gone
|
||||
@@ -72,15 +73,21 @@ const F32 F_E = 2.71828182845904523536f;
|
||||
const F32 F_SQRT2 = 1.4142135623730950488016887242097f;
|
||||
const F32 F_SQRT3 = 1.73205080756888288657986402541f;
|
||||
const F32 OO_SQRT2 = 0.7071067811865475244008443621049f;
|
||||
const F32 OO_SQRT3 = 0.577350269189625764509f;
|
||||
const F32 DEG_TO_RAD = 0.017453292519943295769236907684886f;
|
||||
const F32 RAD_TO_DEG = 57.295779513082320876798154814105f;
|
||||
const F32 F_APPROXIMATELY_ZERO = 0.00001f;
|
||||
const F32 F_LN10 = 2.3025850929940456840179914546844f;
|
||||
const F32 OO_LN10 = 0.43429448190325182765112891891661f;
|
||||
const F32 F_LN2 = 0.69314718056f;
|
||||
const F32 OO_LN2 = 1.4426950408889634073599246810019f;
|
||||
|
||||
const F32 F_ALMOST_ZERO = 0.0001f;
|
||||
const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO;
|
||||
|
||||
const F32 GIMBAL_THRESHOLD = 0.000436f; // sets the gimballock threshold 0.025 away from +/-90 degrees
|
||||
// formula: GIMBAL_THRESHOLD = sin(DEG_TO_RAD * gimbal_threshold_angle);
|
||||
|
||||
// BUG: Eliminate in favor of F_APPROXIMATELY_ZERO above?
|
||||
const F32 FP_MAG_THRESHOLD = 0.0000001f;
|
||||
|
||||
@@ -111,6 +118,12 @@ inline bool is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f <
|
||||
// WARNING: Infinity is comparable with F32_MAX and negative
|
||||
// infinity is comparable with F32_MIN
|
||||
|
||||
// handles negative and positive zeros
|
||||
inline bool is_zero(F32 x)
|
||||
{
|
||||
return (*(U32*)(&x) & 0x7fffffff) == 0;
|
||||
}
|
||||
|
||||
inline bool is_approx_equal(F32 x, F32 y)
|
||||
{
|
||||
const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "sys.h"
|
||||
#include "llmath.h"
|
||||
|
||||
static LL_ALIGN_16(const F32 M_IDENT_3A[12]) =
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
// LLMatrix3a is the base class for LLRotation, which should be used instead any time you're dealing with a
|
||||
// rotation matrix.
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLMatrix3a
|
||||
{
|
||||
public:
|
||||
@@ -113,8 +114,9 @@ protected:
|
||||
|
||||
LL_ALIGN_16(LLVector4a mColumns[3]);
|
||||
|
||||
};
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLRotation : public LLMatrix3a
|
||||
{
|
||||
public:
|
||||
@@ -123,6 +125,6 @@ public:
|
||||
|
||||
// Returns true if this rotation is orthonormal with det ~= 1
|
||||
inline bool isOkRotation() const;
|
||||
};
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,10 +31,72 @@
|
||||
#include "m4math.h"
|
||||
#include "m3math.h"
|
||||
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLMatrix4a
|
||||
{
|
||||
public:
|
||||
private:
|
||||
LL_ALIGN_16(LLVector4a mMatrix[4]);
|
||||
public:
|
||||
enum
|
||||
{
|
||||
ROW_FWD = 0,
|
||||
ROW_LEFT,
|
||||
ROW_UP,
|
||||
ROW_TRANS
|
||||
};
|
||||
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
|
||||
LLMatrix4a()
|
||||
{}
|
||||
LLMatrix4a(const LLQuad& q1,const LLQuad& q2,const LLQuad& q3,const LLQuad& q4)
|
||||
{
|
||||
mMatrix[0] = q1;
|
||||
mMatrix[1] = q2;
|
||||
mMatrix[2] = q3;
|
||||
mMatrix[3] = q4;
|
||||
}
|
||||
LLMatrix4a(const LLQuaternion2& quat)
|
||||
{
|
||||
const LLVector4a& xyzw = quat.getVector4a();
|
||||
LLVector4a nyxwz = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(2,3,0,1));
|
||||
nyxwz.negate();
|
||||
|
||||
const LLVector4a xnyynx = _mm_unpacklo_ps(xyzw,nyxwz);
|
||||
const LLVector4a znwwnz = _mm_unpackhi_ps(xyzw,nyxwz);
|
||||
|
||||
LLMatrix4a mata;
|
||||
mata.setRow<0>(_mm_shuffle_ps(xyzw, xnyynx, _MM_SHUFFLE(0,1,2,3)));
|
||||
mata.setRow<1>(_mm_shuffle_ps(znwwnz, xyzw, _MM_SHUFFLE(1,0,2,3)));
|
||||
mata.setRow<2>(_mm_shuffle_ps(xnyynx, xyzw, _MM_SHUFFLE(2,3,3,2)));
|
||||
mata.setRow<3>(_mm_shuffle_ps(xnyynx, znwwnz, _MM_SHUFFLE(2,3,1,3)));
|
||||
|
||||
LLMatrix4a matb;
|
||||
matb.setRow<0>(_mm_shuffle_ps(xyzw, xnyynx, _MM_SHUFFLE(3,1,2,3)));
|
||||
matb.setRow<1>(_mm_shuffle_ps(znwwnz, xnyynx, _MM_SHUFFLE(1,0,2,3)));
|
||||
matb.setRow<2>(_mm_shuffle_ps(xnyynx, znwwnz, _MM_SHUFFLE(3,2,3,2)));
|
||||
matb.setRow<3>(xyzw);
|
||||
|
||||
setMul(matb,mata);
|
||||
}
|
||||
|
||||
inline F32* getF32ptr()
|
||||
{
|
||||
return mMatrix[0].getF32ptr();
|
||||
}
|
||||
|
||||
inline const F32* getF32ptr() const
|
||||
{
|
||||
return mMatrix[0].getF32ptr();
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
@@ -44,13 +106,21 @@ public:
|
||||
mMatrix[3].clear();
|
||||
}
|
||||
|
||||
inline void setIdentity()
|
||||
{
|
||||
static __m128 ones = _mm_set_ps(1.f,0.f,0.f,1.f);
|
||||
mMatrix[0] = _mm_movelh_ps(ones,_mm_setzero_ps());
|
||||
mMatrix[1] = _mm_movehl_ps(_mm_setzero_ps(),ones);
|
||||
mMatrix[2] = _mm_movelh_ps(_mm_setzero_ps(),ones);
|
||||
mMatrix[3] = _mm_movehl_ps(ones,_mm_setzero_ps());
|
||||
}
|
||||
|
||||
inline void loadu(const LLMatrix4& src)
|
||||
{
|
||||
mMatrix[0] = _mm_loadu_ps(src.mMatrix[0]);
|
||||
mMatrix[1] = _mm_loadu_ps(src.mMatrix[1]);
|
||||
mMatrix[2] = _mm_loadu_ps(src.mMatrix[2]);
|
||||
mMatrix[3] = _mm_loadu_ps(src.mMatrix[3]);
|
||||
|
||||
mMatrix[0].loadua(src.mMatrix[0]);
|
||||
mMatrix[1].loadua(src.mMatrix[1]);
|
||||
mMatrix[2].loadua(src.mMatrix[2]);
|
||||
mMatrix[3].loadua(src.mMatrix[3]);
|
||||
}
|
||||
|
||||
inline void loadu(const LLMatrix3& src)
|
||||
@@ -61,6 +131,14 @@ public:
|
||||
mMatrix[3].set(0,0,0,1.f);
|
||||
}
|
||||
|
||||
inline void loadu(const F32* src)
|
||||
{
|
||||
mMatrix[0].loadua(src+0);
|
||||
mMatrix[1].loadua(src+4);
|
||||
mMatrix[2].loadua(src+8);
|
||||
mMatrix[3].loadua(src+12);
|
||||
}
|
||||
|
||||
inline void add(const LLMatrix4a& rhs)
|
||||
{
|
||||
mMatrix[0].add(rhs.mMatrix[0]);
|
||||
@@ -69,6 +147,75 @@ public:
|
||||
mMatrix[3].add(rhs.mMatrix[3]);
|
||||
}
|
||||
|
||||
inline void mul(const LLMatrix4a& rhs)
|
||||
{
|
||||
//Not using rotate4 to avoid extra copy of *this.
|
||||
LLVector4a x0,y0,z0,w0;
|
||||
LLVector4a x1,y1,z1,w1;
|
||||
LLVector4a x2,y2,z2,w2;
|
||||
LLVector4a x3,y3,z3,w3;
|
||||
|
||||
//16 shuffles
|
||||
x0.splat<0>(rhs.mMatrix[0]);
|
||||
x1.splat<0>(rhs.mMatrix[1]);
|
||||
x2.splat<0>(rhs.mMatrix[2]);
|
||||
x3.splat<0>(rhs.mMatrix[3]);
|
||||
|
||||
y0.splat<1>(rhs.mMatrix[0]);
|
||||
y1.splat<1>(rhs.mMatrix[1]);
|
||||
y2.splat<1>(rhs.mMatrix[2]);
|
||||
y3.splat<1>(rhs.mMatrix[3]);
|
||||
|
||||
z0.splat<2>(rhs.mMatrix[0]);
|
||||
z1.splat<2>(rhs.mMatrix[1]);
|
||||
z2.splat<2>(rhs.mMatrix[2]);
|
||||
z3.splat<2>(rhs.mMatrix[3]);
|
||||
|
||||
w0.splat<3>(rhs.mMatrix[0]);
|
||||
w1.splat<3>(rhs.mMatrix[1]);
|
||||
w2.splat<3>(rhs.mMatrix[2]);
|
||||
w3.splat<3>(rhs.mMatrix[3]);
|
||||
|
||||
//16 muls
|
||||
x0.mul(mMatrix[0]);
|
||||
x1.mul(mMatrix[0]);
|
||||
x2.mul(mMatrix[0]);
|
||||
x3.mul(mMatrix[0]);
|
||||
|
||||
y0.mul(mMatrix[1]);
|
||||
y1.mul(mMatrix[1]);
|
||||
y2.mul(mMatrix[1]);
|
||||
y3.mul(mMatrix[1]);
|
||||
|
||||
z0.mul(mMatrix[2]);
|
||||
z1.mul(mMatrix[2]);
|
||||
z2.mul(mMatrix[2]);
|
||||
z3.mul(mMatrix[2]);
|
||||
|
||||
w0.mul(mMatrix[3]);
|
||||
w1.mul(mMatrix[3]);
|
||||
w2.mul(mMatrix[3]);
|
||||
w3.mul(mMatrix[3]);
|
||||
|
||||
//12 adds
|
||||
x0.add(y0);
|
||||
z0.add(w0);
|
||||
|
||||
x1.add(y1);
|
||||
z1.add(w1);
|
||||
|
||||
x2.add(y2);
|
||||
z2.add(w2);
|
||||
|
||||
x3.add(y3);
|
||||
z3.add(w3);
|
||||
|
||||
mMatrix[0].setAdd(x0,z0);
|
||||
mMatrix[1].setAdd(x1,z1);
|
||||
mMatrix[2].setAdd(x2,z2);
|
||||
mMatrix[3].setAdd(x3,z3);
|
||||
}
|
||||
|
||||
inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2)
|
||||
{
|
||||
mMatrix[0] = r0;
|
||||
@@ -76,6 +223,44 @@ public:
|
||||
mMatrix[2] = r2;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline void setRow(const LLVector4a& row)
|
||||
{
|
||||
mMatrix[N] = row;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline const LLVector4a& getRow() const
|
||||
{
|
||||
return mMatrix[N];
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline LLVector4a& getRow()
|
||||
{
|
||||
return mMatrix[N];
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline void setColumn(const LLVector4a& col)
|
||||
{
|
||||
mMatrix[0].copyComponent<N>(col.getScalarAt<0>());
|
||||
mMatrix[1].copyComponent<N>(col.getScalarAt<1>());
|
||||
mMatrix[2].copyComponent<N>(col.getScalarAt<2>());
|
||||
mMatrix[3].copyComponent<N>(col.getScalarAt<3>());
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline LLVector4a getColumn()
|
||||
{
|
||||
LLVector4a v;
|
||||
v.copyComponent<0>(mMatrix[0].getScalarAt<N>());
|
||||
v.copyComponent<1>(mMatrix[1].getScalarAt<N>());
|
||||
v.copyComponent<2>(mMatrix[2].getScalarAt<N>());
|
||||
v.copyComponent<3>(mMatrix[3].getScalarAt<N>());
|
||||
return v;
|
||||
}
|
||||
|
||||
inline void setMul(const LLMatrix4a& m, const F32 s)
|
||||
{
|
||||
mMatrix[0].setMul(m.mMatrix[0], s);
|
||||
@@ -84,6 +269,14 @@ public:
|
||||
mMatrix[3].setMul(m.mMatrix[3], s);
|
||||
}
|
||||
|
||||
inline void setMul(const LLMatrix4a& m0, const LLMatrix4a& m1)
|
||||
{
|
||||
m0.rotate4(m1.mMatrix[0],mMatrix[0]);
|
||||
m0.rotate4(m1.mMatrix[1],mMatrix[1]);
|
||||
m0.rotate4(m1.mMatrix[2],mMatrix[2]);
|
||||
m0.rotate4(m1.mMatrix[3],mMatrix[3]);
|
||||
}
|
||||
|
||||
inline void setLerp(const LLMatrix4a& a, const LLMatrix4a& b, F32 w)
|
||||
{
|
||||
LLVector4a d0,d1,d2,d3;
|
||||
@@ -107,13 +300,14 @@ public:
|
||||
|
||||
//Singu Note: Don't mess with this. It's intentionally different from LL's.
|
||||
// Note how res isn't manipulated until the very end.
|
||||
//Fast(er). Treats v[VW] as 0.f
|
||||
inline void rotate(const LLVector4a& v, LLVector4a& res) const
|
||||
{
|
||||
LLVector4a x,y,z;
|
||||
|
||||
x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
|
||||
z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
|
||||
x.splat<0>(v);
|
||||
y.splat<1>(v);
|
||||
z.splat<2>(v);
|
||||
|
||||
x.mul(mMatrix[0]);
|
||||
y.mul(mMatrix[1]);
|
||||
@@ -123,14 +317,15 @@ public:
|
||||
res.setAdd(x,z);
|
||||
}
|
||||
|
||||
//Proper. v[VW] as v[VW]
|
||||
inline void rotate4(const LLVector4a& v, LLVector4a& res) const
|
||||
{
|
||||
LLVector4a x,y,z,w;
|
||||
|
||||
x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
|
||||
z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
|
||||
w = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
x.splat<0>(v);
|
||||
y.splat<1>(v);
|
||||
z.splat<2>(v);
|
||||
w.splat<3>(v);
|
||||
|
||||
x.mul(mMatrix[0]);
|
||||
y.mul(mMatrix[1]);
|
||||
@@ -142,14 +337,15 @@ public:
|
||||
res.setAdd(x,z);
|
||||
}
|
||||
|
||||
//Fast(er). Treats v[VW] as 1.f
|
||||
inline void affineTransform(const LLVector4a& v, LLVector4a& res) const
|
||||
{
|
||||
LLVector4a x,y,z;
|
||||
|
||||
x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
|
||||
z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
|
||||
|
||||
x.splat<0>(v);
|
||||
y.splat<1>(v);
|
||||
z.splat<2>(v);
|
||||
|
||||
x.mul(mMatrix[0]);
|
||||
y.mul(mMatrix[1]);
|
||||
z.mul(mMatrix[2]);
|
||||
@@ -158,6 +354,348 @@ public:
|
||||
z.add(mMatrix[3]);
|
||||
res.setAdd(x,z);
|
||||
}
|
||||
};
|
||||
|
||||
inline void perspectiveTransform(const LLVector4a& v, LLVector4a& res) const
|
||||
{
|
||||
LLVector4a x,y,z,s,t,p,q;
|
||||
|
||||
x.splat<0>(v);
|
||||
y.splat<1>(v);
|
||||
z.splat<2>(v);
|
||||
|
||||
s.splat<3>(mMatrix[0]);
|
||||
t.splat<3>(mMatrix[1]);
|
||||
p.splat<3>(mMatrix[2]);
|
||||
q.splat<3>(mMatrix[3]);
|
||||
|
||||
s.mul(x);
|
||||
t.mul(y);
|
||||
p.mul(z);
|
||||
q.add(s);
|
||||
t.add(p);
|
||||
q.add(t);
|
||||
|
||||
x.mul(mMatrix[0]);
|
||||
y.mul(mMatrix[1]);
|
||||
z.mul(mMatrix[2]);
|
||||
|
||||
x.add(y);
|
||||
z.add(mMatrix[3]);
|
||||
res.setAdd(x,z);
|
||||
res.div(q);
|
||||
}
|
||||
|
||||
inline void transpose()
|
||||
{
|
||||
__m128 q1 = _mm_unpackhi_ps(mMatrix[0],mMatrix[1]);
|
||||
__m128 q2 = _mm_unpacklo_ps(mMatrix[0],mMatrix[1]);
|
||||
__m128 q3 = _mm_unpacklo_ps(mMatrix[2],mMatrix[3]);
|
||||
__m128 q4 = _mm_unpackhi_ps(mMatrix[2],mMatrix[3]);
|
||||
|
||||
mMatrix[0] = _mm_movelh_ps(q2,q3);
|
||||
mMatrix[1] = _mm_movehl_ps(q3,q2);
|
||||
mMatrix[2] = _mm_movelh_ps(q1,q4);
|
||||
mMatrix[3] = _mm_movehl_ps(q4,q1);
|
||||
}
|
||||
|
||||
// Following procedure adapted from:
|
||||
// http://software.intel.com/en-us/articles/optimized-matrix-library-for-use-with-the-intel-pentiumr-4-processors-sse2-instructions/
|
||||
//
|
||||
// License/Copyright Statement:
|
||||
//
|
||||
// Copyright (c) 2001 Intel Corporation.
|
||||
//
|
||||
// Permition is granted to use, copy, distribute and prepare derivative works
|
||||
// of this library for any purpose and without fee, provided, that the above
|
||||
// copyright notice and this statement appear in all copies.
|
||||
// Intel makes no representations about the suitability of this library for
|
||||
// any purpose, and specifically disclaims all warranties.
|
||||
// See LEGAL-intel_matrixlib.TXT for all the legal information.
|
||||
inline float invert()
|
||||
{
|
||||
LL_ALIGN_16(const unsigned int Sign_PNNP[4]) = { 0x00000000, 0x80000000, 0x80000000, 0x00000000 };
|
||||
|
||||
// The inverse is calculated using "Divide and Conquer" technique. The
|
||||
// original matrix is divide into four 2x2 sub-matrices. Since each
|
||||
// register holds four matrix element, the smaller matrices are
|
||||
// represented as a registers. Hence we get a better locality of the
|
||||
// calculations.
|
||||
|
||||
LLVector4a A = _mm_movelh_ps(mMatrix[0], mMatrix[1]), // the four sub-matrices
|
||||
B = _mm_movehl_ps(mMatrix[1], mMatrix[0]),
|
||||
C = _mm_movelh_ps(mMatrix[2], mMatrix[3]),
|
||||
D = _mm_movehl_ps(mMatrix[3], mMatrix[2]);
|
||||
LLVector4a iA, iB, iC, iD, // partial inverse of the sub-matrices
|
||||
DC, AB;
|
||||
LLSimdScalar dA, dB, dC, dD; // determinant of the sub-matrices
|
||||
LLSimdScalar det, d, d1, d2;
|
||||
LLVector4a rd;
|
||||
|
||||
// AB = A# * B
|
||||
AB.setMul(_mm_shuffle_ps(A,A,0x0F), B);
|
||||
AB.sub(_mm_mul_ps(_mm_shuffle_ps(A,A,0xA5), _mm_shuffle_ps(B,B,0x4E)));
|
||||
// DC = D# * C
|
||||
DC.setMul(_mm_shuffle_ps(D,D,0x0F), C);
|
||||
DC.sub(_mm_mul_ps(_mm_shuffle_ps(D,D,0xA5), _mm_shuffle_ps(C,C,0x4E)));
|
||||
|
||||
// dA = |A|
|
||||
dA = _mm_mul_ps(_mm_shuffle_ps(A, A, 0x5F),A);
|
||||
dA -= _mm_movehl_ps(dA,dA);
|
||||
// dB = |B|
|
||||
dB = _mm_mul_ps(_mm_shuffle_ps(B, B, 0x5F),B);
|
||||
dB -= _mm_movehl_ps(dB,dB);
|
||||
|
||||
// dC = |C|
|
||||
dC = _mm_mul_ps(_mm_shuffle_ps(C, C, 0x5F),C);
|
||||
dC -= _mm_movehl_ps(dC,dC);
|
||||
// dD = |D|
|
||||
dD = _mm_mul_ps(_mm_shuffle_ps(D, D, 0x5F),D);
|
||||
dD -= _mm_movehl_ps(dD,dD);
|
||||
|
||||
// d = trace(AB*DC) = trace(A#*B*D#*C)
|
||||
d = _mm_mul_ps(_mm_shuffle_ps(DC,DC,0xD8),AB);
|
||||
|
||||
// iD = C*A#*B
|
||||
iD.setMul(_mm_shuffle_ps(C,C,0xA0), _mm_movelh_ps(AB,AB));
|
||||
iD.add(_mm_mul_ps(_mm_shuffle_ps(C,C,0xF5), _mm_movehl_ps(AB,AB)));
|
||||
// iA = B*D#*C
|
||||
iA.setMul(_mm_shuffle_ps(B,B,0xA0), _mm_movelh_ps(DC,DC));
|
||||
iA.add(_mm_mul_ps(_mm_shuffle_ps(B,B,0xF5), _mm_movehl_ps(DC,DC)));
|
||||
|
||||
// d = trace(AB*DC) = trace(A#*B*D#*C) [continue]
|
||||
d = _mm_add_ps(d, _mm_movehl_ps(d, d));
|
||||
d += _mm_shuffle_ps(d, d, 1);
|
||||
d1 = dA*dD;
|
||||
d2 = dB*dC;
|
||||
|
||||
// iD = D*|A| - C*A#*B
|
||||
iD.setSub(_mm_mul_ps(D,_mm_shuffle_ps(dA,dA,0)), iD);
|
||||
|
||||
// iA = A*|D| - B*D#*C;
|
||||
iA.setSub(_mm_mul_ps(A,_mm_shuffle_ps(dD,dD,0)), iA);
|
||||
|
||||
// det = |A|*|D| + |B|*|C| - trace(A#*B*D#*C)
|
||||
det = d1+d2-d;
|
||||
|
||||
__m128 is_zero_mask = _mm_cmpeq_ps(det,_mm_setzero_ps());
|
||||
rd = _mm_div_ss(_mm_set_ss(1.f),_mm_or_ps(_mm_andnot_ps(is_zero_mask, det), _mm_and_ps(is_zero_mask, _mm_set_ss(1.f))));
|
||||
#ifdef ZERO_SINGULAR
|
||||
rd = _mm_and_ps(_mm_cmpneq_ss(det,_mm_setzero_ps()), rd);
|
||||
#endif
|
||||
|
||||
// iB = D * (A#B)# = D*B#*A
|
||||
iB.setMul(D, _mm_shuffle_ps(AB,AB,0x33));
|
||||
iB.sub(_mm_mul_ps(_mm_shuffle_ps(D,D,0xB1), _mm_shuffle_ps(AB,AB,0x66)));
|
||||
// iC = A * (D#C)# = A*C#*D
|
||||
iC.setMul(A, _mm_shuffle_ps(DC,DC,0x33));
|
||||
iC.sub(_mm_mul_ps(_mm_shuffle_ps(A,A,0xB1), _mm_shuffle_ps(DC,DC,0x66)));
|
||||
|
||||
rd = _mm_shuffle_ps(rd,rd,0);
|
||||
rd = _mm_xor_ps(rd, _mm_load_ps((const float*)Sign_PNNP));
|
||||
|
||||
// iB = C*|B| - D*B#*A
|
||||
iB.setSub(_mm_mul_ps(C,_mm_shuffle_ps(dB,dB,0)), iB);
|
||||
|
||||
// iC = B*|C| - A*C#*D;
|
||||
iC.setSub(_mm_mul_ps(B,_mm_shuffle_ps(dC,dC,0)), iC);
|
||||
|
||||
|
||||
// iX = iX / det
|
||||
iA.mul(rd);
|
||||
iB.mul(rd);
|
||||
iC.mul(rd);
|
||||
iD.mul(rd);
|
||||
|
||||
mMatrix[0] = _mm_shuffle_ps(iA,iB,0x77);
|
||||
mMatrix[1] = _mm_shuffle_ps(iA,iB,0x22);
|
||||
mMatrix[2] = _mm_shuffle_ps(iC,iD,0x77);
|
||||
mMatrix[3] = _mm_shuffle_ps(iC,iD,0x22);
|
||||
|
||||
F32 ret;
|
||||
_mm_store_ss(&ret,det);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//=============Affine transformation matrix only=========================
|
||||
|
||||
//Multiply matrix with a pure translation matrix.
|
||||
inline void applyTranslation_affine(const F32& x, const F32& y, const F32& z)
|
||||
{
|
||||
const LLVector4a xyz0(x,y,z,0); //load
|
||||
LLVector4a xxxx;
|
||||
xxxx.splat<0>(xyz0);
|
||||
LLVector4a yyyy;
|
||||
yyyy.splat<1>(xyz0);
|
||||
LLVector4a zzzz;
|
||||
zzzz.splat<2>(xyz0);
|
||||
|
||||
LLVector4a sum1;
|
||||
LLVector4a sum2;
|
||||
LLVector4a sum3;
|
||||
|
||||
sum1.setMul(xxxx,mMatrix[0]);
|
||||
sum2.setMul(yyyy,mMatrix[1]);
|
||||
sum3.setMul(zzzz,mMatrix[2]);
|
||||
|
||||
mMatrix[3].add(sum1);
|
||||
mMatrix[3].add(sum2);
|
||||
mMatrix[3].add(sum3);
|
||||
}
|
||||
|
||||
//Multiply matrix with a pure translation matrix.
|
||||
inline void applyTranslation_affine(const LLVector3& trans)
|
||||
{
|
||||
applyTranslation_affine(trans.mV[VX],trans.mV[VY],trans.mV[VZ]);
|
||||
}
|
||||
|
||||
//Multiply matrix with a pure scale matrix.
|
||||
inline void applyScale_affine(const F32& x, const F32& y, const F32& z)
|
||||
{
|
||||
const LLVector4a xyz0(x,y,z,0); //load
|
||||
LLVector4a xxxx;
|
||||
xxxx.splat<0>(xyz0);
|
||||
LLVector4a yyyy;
|
||||
yyyy.splat<1>(xyz0);
|
||||
LLVector4a zzzz;
|
||||
zzzz.splat<2>(xyz0);
|
||||
|
||||
mMatrix[0].mul(xxxx);
|
||||
mMatrix[1].mul(yyyy);
|
||||
mMatrix[2].mul(zzzz);
|
||||
}
|
||||
|
||||
//Multiply matrix with a pure scale matrix.
|
||||
inline void applyScale_affine(const LLVector3& scale)
|
||||
{
|
||||
applyScale_affine(scale.mV[VX],scale.mV[VY],scale.mV[VZ]);
|
||||
}
|
||||
|
||||
//Multiply matrix with a pure scale matrix.
|
||||
inline void applyScale_affine(const F32& s)
|
||||
{
|
||||
const LLVector4a scale(s); //load
|
||||
mMatrix[0].mul(scale);
|
||||
mMatrix[1].mul(scale);
|
||||
mMatrix[2].mul(scale);
|
||||
}
|
||||
|
||||
//Direct addition to row3.
|
||||
inline void translate_affine(const LLVector3& trans)
|
||||
{
|
||||
LLVector4a translation;
|
||||
translation.load3(trans.mV);
|
||||
mMatrix[3].add(translation);
|
||||
}
|
||||
|
||||
//Direct assignment of row3.
|
||||
inline void setTranslate_affine(const LLVector3& trans)
|
||||
{
|
||||
static const LLVector4Logical mask = _mm_load_ps((F32*)&S_V4LOGICAL_MASK_TABLE[3*4]);
|
||||
|
||||
LLVector4a translation;
|
||||
translation.load3(trans.mV);
|
||||
|
||||
mMatrix[3].setSelectWithMask(mask,mMatrix[3],translation);
|
||||
}
|
||||
|
||||
inline void mul_affine(const LLMatrix4a& rhs)
|
||||
{
|
||||
LLVector4a x0,y0,z0;
|
||||
LLVector4a x1,y1,z1;
|
||||
LLVector4a x2,y2,z2;
|
||||
LLVector4a x3,y3,z3;
|
||||
|
||||
//12 shuffles
|
||||
x0.splat<0>(rhs.mMatrix[0]);
|
||||
x1.splat<0>(rhs.mMatrix[1]);
|
||||
x2.splat<0>(rhs.mMatrix[2]);
|
||||
x3.splat<0>(rhs.mMatrix[3]);
|
||||
|
||||
y0.splat<1>(rhs.mMatrix[0]);
|
||||
y1.splat<1>(rhs.mMatrix[1]);
|
||||
y2.splat<1>(rhs.mMatrix[2]);
|
||||
y3.splat<1>(rhs.mMatrix[3]);
|
||||
|
||||
z0.splat<2>(rhs.mMatrix[0]);
|
||||
z1.splat<2>(rhs.mMatrix[1]);
|
||||
z2.splat<2>(rhs.mMatrix[2]);
|
||||
z3.splat<2>(rhs.mMatrix[3]);
|
||||
|
||||
//12 muls
|
||||
x0.mul(mMatrix[0]);
|
||||
x1.mul(mMatrix[0]);
|
||||
x2.mul(mMatrix[0]);
|
||||
x3.mul(mMatrix[0]);
|
||||
|
||||
y0.mul(mMatrix[1]);
|
||||
y1.mul(mMatrix[1]);
|
||||
y2.mul(mMatrix[1]);
|
||||
y3.mul(mMatrix[1]);
|
||||
|
||||
z0.mul(mMatrix[2]);
|
||||
z1.mul(mMatrix[2]);
|
||||
z2.mul(mMatrix[2]);
|
||||
z3.mul(mMatrix[2]);
|
||||
|
||||
//9 adds
|
||||
x0.add(y0);
|
||||
|
||||
x1.add(y1);
|
||||
|
||||
x2.add(y2);
|
||||
|
||||
x3.add(y3);
|
||||
z3.add(mMatrix[3]);
|
||||
|
||||
mMatrix[0].setAdd(x0,z0);
|
||||
mMatrix[1].setAdd(x1,z1);
|
||||
mMatrix[2].setAdd(x2,z2);
|
||||
mMatrix[3].setAdd(x3,z3);
|
||||
}
|
||||
|
||||
inline void extractRotation_affine()
|
||||
{
|
||||
static const LLVector4Logical mask = _mm_load_ps((F32*)&S_V4LOGICAL_MASK_TABLE[3*4]);
|
||||
mMatrix[0].setSelectWithMask(mask,_mm_setzero_ps(),mMatrix[0]);
|
||||
mMatrix[1].setSelectWithMask(mask,_mm_setzero_ps(),mMatrix[1]);
|
||||
mMatrix[2].setSelectWithMask(mask,_mm_setzero_ps(),mMatrix[2]);
|
||||
mMatrix[3].setSelectWithMask(mask,LLVector4a(1.f),_mm_setzero_ps());
|
||||
}
|
||||
|
||||
//======================Logic====================
|
||||
private:
|
||||
template<bool mins> inline void init_foos(LLMatrix4a& foos) const
|
||||
{
|
||||
static bool done(false);
|
||||
if (done) return;
|
||||
const LLVector4a delta(0.0001f);
|
||||
foos.setIdentity();
|
||||
foos.getRow<0>().sub(delta);
|
||||
foos.getRow<1>().sub(delta);
|
||||
foos.getRow<2>().sub(delta);
|
||||
foos.getRow<3>().sub(delta);
|
||||
done = true;
|
||||
}
|
||||
|
||||
public:
|
||||
inline bool isIdentity() const
|
||||
{
|
||||
static LLMatrix4a mins;
|
||||
static LLMatrix4a maxs;
|
||||
|
||||
init_foos<false>(mins);
|
||||
init_foos<true>(maxs);
|
||||
|
||||
LLVector4a mask1 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[0],mins.getRow<0>()), _mm_cmplt_ps(mMatrix[0],maxs.getRow<0>()));
|
||||
LLVector4a mask2 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[1],mins.getRow<1>()), _mm_cmplt_ps(mMatrix[1],maxs.getRow<1>()));
|
||||
LLVector4a mask3 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[2],mins.getRow<2>()), _mm_cmplt_ps(mMatrix[2],maxs.getRow<2>()));
|
||||
LLVector4a mask4 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[3],mins.getRow<3>()), _mm_cmplt_ps(mMatrix[3],maxs.getRow<3>()));
|
||||
|
||||
mask1 = _mm_and_ps(mask1,mask2);
|
||||
mask2 = _mm_and_ps(mask3,mask4);
|
||||
|
||||
return _mm_movemask_epi8(_mm_castps_si128(_mm_and_ps(mask1, mask2))) == 0xFFFF;
|
||||
}
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,36 +2,28 @@
|
||||
* @file llmodularmath.cpp
|
||||
* @brief LLModularMath class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2010, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlife.com/developers/opensource/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlife.com/developers/opensource/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llmodularmath.h
|
||||
* @brief Useful modular math functions.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -932,10 +932,10 @@ protected:
|
||||
MIN = 3
|
||||
} eDName;
|
||||
|
||||
LLVector4a mCenter;
|
||||
LLVector4a mSize;
|
||||
LLVector4a mMax;
|
||||
LLVector4a mMin;
|
||||
LL_ALIGN_16(LLVector4a mCenter);
|
||||
LL_ALIGN_16(LLVector4a mSize);
|
||||
LL_ALIGN_16(LLVector4a mMax);
|
||||
LL_ALIGN_16(LLVector4a mMin);
|
||||
|
||||
oct_node* mParent;
|
||||
U8 mOctant;
|
||||
@@ -964,6 +964,26 @@ public:
|
||||
: BaseType(center, size, parent)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef LL_OCTREE_POOLS
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return LLOctreeNode<T>::getPool(size).malloc();
|
||||
}
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
LLOctreeNode<T>::getPool(sizeof(LLOctreeNode<T>)).free(ptr);
|
||||
}
|
||||
#else
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool balance()
|
||||
{
|
||||
|
||||
@@ -1,31 +1,25 @@
|
||||
/**
|
||||
* @file llperlin.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,31 +1,25 @@
|
||||
/**
|
||||
* @file llperlin.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,31 +1,25 @@
|
||||
/**
|
||||
* @file llplane.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -100,8 +94,14 @@ public:
|
||||
return mV.greaterEqual(LLVector4a::getZero()).getGatheredBits() & LLVector4Logical::MASK_XYZ;
|
||||
}
|
||||
|
||||
//check if two planes are nearly same
|
||||
bool equal(const LLPlane& p) const
|
||||
{
|
||||
return mV.equals4(p.mV);
|
||||
}
|
||||
|
||||
private:
|
||||
LLVector4a mV;
|
||||
LL_ALIGN_16(LLVector4a mV);
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
|
||||
|
||||
@@ -3,31 +3,25 @@
|
||||
* @brief useful routines for quantizing floats to various length ints
|
||||
* and back out again
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llquaternion.cpp
|
||||
* @brief LLQuaternion class implementation.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -64,34 +58,40 @@ LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
|
||||
|
||||
LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
|
||||
{
|
||||
LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
|
||||
v.normalize();
|
||||
|
||||
F32 c, s;
|
||||
c = cosf(angle*0.5f);
|
||||
s = sinf(angle*0.5f);
|
||||
|
||||
mQ[VX] = v.mV[VX] * s;
|
||||
mQ[VY] = v.mV[VY] * s;
|
||||
mQ[VZ] = v.mV[VZ] * s;
|
||||
mQ[VW] = c;
|
||||
normalize();
|
||||
F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
angle *= 0.5;
|
||||
F32 c = cosf(angle);
|
||||
F32 s = sinf(angle) / mag;
|
||||
mQ[VX] = vec.mV[VX] * s;
|
||||
mQ[VY] = vec.mV[VY] * s;
|
||||
mQ[VZ] = vec.mV[VZ] * s;
|
||||
mQ[VW] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec)
|
||||
{
|
||||
LLVector3 v(vec);
|
||||
v.normalize();
|
||||
|
||||
F32 c, s;
|
||||
c = cosf(angle*0.5f);
|
||||
s = sinf(angle*0.5f);
|
||||
|
||||
mQ[VX] = v.mV[VX] * s;
|
||||
mQ[VY] = v.mV[VY] * s;
|
||||
mQ[VZ] = v.mV[VZ] * s;
|
||||
mQ[VW] = c;
|
||||
normalize();
|
||||
F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
angle *= 0.5;
|
||||
F32 c = cosf(angle);
|
||||
F32 s = sinf(angle) / mag;
|
||||
mQ[VX] = vec.mV[VX] * s;
|
||||
mQ[VY] = vec.mV[VY] * s;
|
||||
mQ[VZ] = vec.mV[VZ] * s;
|
||||
mQ[VW] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadIdentity();
|
||||
}
|
||||
}
|
||||
|
||||
LLQuaternion::LLQuaternion(const LLVector3 &x_axis,
|
||||
@@ -142,57 +142,61 @@ void LLQuaternion::quantize8(F32 lower, F32 upper)
|
||||
|
||||
const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, F32 x, F32 y, F32 z)
|
||||
{
|
||||
LLVector3 vec(x, y, z);
|
||||
vec.normalize();
|
||||
|
||||
angle *= 0.5f;
|
||||
F32 c, s;
|
||||
c = cosf(angle);
|
||||
s = sinf(angle);
|
||||
|
||||
mQ[VX] = vec.mV[VX]*s;
|
||||
mQ[VY] = vec.mV[VY]*s;
|
||||
mQ[VZ] = vec.mV[VZ]*s;
|
||||
mQ[VW] = c;
|
||||
|
||||
normalize();
|
||||
F32 mag = sqrtf(x * x + y * y + z * z);
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
angle *= 0.5;
|
||||
F32 c = cosf(angle);
|
||||
F32 s = sinf(angle) / mag;
|
||||
mQ[VX] = x * s;
|
||||
mQ[VY] = y * s;
|
||||
mQ[VZ] = z * s;
|
||||
mQ[VW] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadIdentity();
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector3 &vec)
|
||||
{
|
||||
LLVector3 v(vec);
|
||||
v.normalize();
|
||||
|
||||
angle *= 0.5f;
|
||||
F32 c, s;
|
||||
c = cosf(angle);
|
||||
s = sinf(angle);
|
||||
|
||||
mQ[VX] = v.mV[VX]*s;
|
||||
mQ[VY] = v.mV[VY]*s;
|
||||
mQ[VZ] = v.mV[VZ]*s;
|
||||
mQ[VW] = c;
|
||||
|
||||
normalize();
|
||||
F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
angle *= 0.5;
|
||||
F32 c = cosf(angle);
|
||||
F32 s = sinf(angle) / mag;
|
||||
mQ[VX] = vec.mV[VX] * s;
|
||||
mQ[VY] = vec.mV[VY] * s;
|
||||
mQ[VZ] = vec.mV[VZ] * s;
|
||||
mQ[VW] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadIdentity();
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector4 &vec)
|
||||
{
|
||||
LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
|
||||
v.normalize();
|
||||
|
||||
F32 c, s;
|
||||
c = cosf(angle*0.5f);
|
||||
s = sinf(angle*0.5f);
|
||||
|
||||
mQ[VX] = v.mV[VX]*s;
|
||||
mQ[VY] = v.mV[VY]*s;
|
||||
mQ[VZ] = v.mV[VZ]*s;
|
||||
mQ[VW] = c;
|
||||
|
||||
normalize();
|
||||
F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
angle *= 0.5;
|
||||
F32 c = cosf(angle);
|
||||
F32 s = sinf(angle) / mag;
|
||||
mQ[VX] = vec.mV[VX] * s;
|
||||
mQ[VY] = vec.mV[VY] * s;
|
||||
mQ[VZ] = vec.mV[VZ] * s;
|
||||
mQ[VW] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadIdentity();
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
@@ -225,68 +229,80 @@ const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat)
|
||||
// deprecated
|
||||
const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z)
|
||||
{
|
||||
LLVector3 vec(x, y, z);
|
||||
vec.normalize();
|
||||
|
||||
angle *= 0.5f;
|
||||
F32 c, s;
|
||||
c = cosf(angle);
|
||||
s = sinf(angle);
|
||||
|
||||
mQ[VX] = vec.mV[VX]*s;
|
||||
mQ[VY] = vec.mV[VY]*s;
|
||||
mQ[VZ] = vec.mV[VZ]*s;
|
||||
mQ[VW] = c;
|
||||
|
||||
normalize();
|
||||
F32 mag = sqrtf(x * x + y * y + z * z);
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
angle *= 0.5;
|
||||
F32 c = cosf(angle);
|
||||
F32 s = sinf(angle) / mag;
|
||||
mQ[VX] = x * s;
|
||||
mQ[VY] = y * s;
|
||||
mQ[VZ] = z * s;
|
||||
mQ[VW] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadIdentity();
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
// deprecated
|
||||
const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec)
|
||||
{
|
||||
LLVector3 v(vec);
|
||||
v.normalize();
|
||||
|
||||
angle *= 0.5f;
|
||||
F32 c, s;
|
||||
c = cosf(angle);
|
||||
s = sinf(angle);
|
||||
|
||||
mQ[VX] = v.mV[VX]*s;
|
||||
mQ[VY] = v.mV[VY]*s;
|
||||
mQ[VZ] = v.mV[VZ]*s;
|
||||
mQ[VW] = c;
|
||||
|
||||
normalize();
|
||||
F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
angle *= 0.5;
|
||||
F32 c = cosf(angle);
|
||||
F32 s = sinf(angle) / mag;
|
||||
mQ[VX] = vec.mV[VX] * s;
|
||||
mQ[VY] = vec.mV[VY] * s;
|
||||
mQ[VZ] = vec.mV[VZ] * s;
|
||||
mQ[VW] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadIdentity();
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec)
|
||||
{
|
||||
LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
|
||||
v.normalize();
|
||||
|
||||
F32 c, s;
|
||||
c = cosf(angle*0.5f);
|
||||
s = sinf(angle*0.5f);
|
||||
|
||||
mQ[VX] = v.mV[VX]*s;
|
||||
mQ[VY] = v.mV[VY]*s;
|
||||
mQ[VZ] = v.mV[VZ]*s;
|
||||
mQ[VW] = c;
|
||||
|
||||
normalize();
|
||||
F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
angle *= 0.5;
|
||||
F32 c = cosf(angle);
|
||||
F32 s = sinf(angle) / mag;
|
||||
mQ[VX] = vec.mV[VX] * s;
|
||||
mQ[VY] = vec.mV[VY] * s;
|
||||
mQ[VZ] = vec.mV[VZ] * s;
|
||||
mQ[VW] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadIdentity();
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
const LLQuaternion& LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw)
|
||||
{
|
||||
LLMatrix3 rot_mat(roll, pitch, yaw);
|
||||
rot_mat.orthogonalize();
|
||||
*this = rot_mat.quaternion();
|
||||
|
||||
normalize();
|
||||
roll *= 0.5f;
|
||||
pitch *= 0.5f;
|
||||
yaw *= 0.5f;
|
||||
F32 sinX = sinf(roll);
|
||||
F32 cosX = cosf(roll);
|
||||
F32 sinY = sinf(pitch);
|
||||
F32 cosY = cosf(pitch);
|
||||
F32 sinZ = sinf(yaw);
|
||||
F32 cosZ = cosf(yaw);
|
||||
mQ[VW] = cosX * cosY * cosZ - sinX * sinY * sinZ;
|
||||
mQ[VX] = sinX * cosY * cosZ + cosX * sinY * sinZ;
|
||||
mQ[VY] = cosX * sinY * cosZ - sinX * cosY * sinZ;
|
||||
mQ[VZ] = cosX * cosY * sinZ + sinX * sinY * cosZ;
|
||||
return (*this);
|
||||
}
|
||||
|
||||
@@ -431,68 +447,44 @@ LLMatrix4 LLQuaternion::getMatrix4(void) const
|
||||
// calculate the shortest rotation from a to b
|
||||
void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b)
|
||||
{
|
||||
// Make a local copy of both vectors.
|
||||
LLVector3 vec_a = a;
|
||||
LLVector3 vec_b = b;
|
||||
|
||||
// Make sure neither vector is zero length. Also normalize
|
||||
// the vectors while we are at it.
|
||||
F32 vec_a_mag = vec_a.normalize();
|
||||
F32 vec_b_mag = vec_b.normalize();
|
||||
if (vec_a_mag < F_APPROXIMATELY_ZERO ||
|
||||
vec_b_mag < F_APPROXIMATELY_ZERO)
|
||||
F32 ab = a * b; // dotproduct
|
||||
LLVector3 c = a % b; // crossproduct
|
||||
F32 cc = c * c; // squared length of the crossproduct
|
||||
if (ab * ab + cc) // test if the arguments have sufficient magnitude
|
||||
{
|
||||
// Can't calculate a rotation from this.
|
||||
// Just return ZERO_ROTATION instead.
|
||||
loadIdentity();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create an axis to rotate around, and the cos of the angle to rotate.
|
||||
LLVector3 axis = vec_a % vec_b;
|
||||
F32 cos_theta = vec_a * vec_b;
|
||||
|
||||
// Check the angle between the vectors to see if they are parallel or anti-parallel.
|
||||
if (cos_theta > 1.0 - F_APPROXIMATELY_ZERO)
|
||||
{
|
||||
// a and b are parallel. No rotation is necessary.
|
||||
loadIdentity();
|
||||
}
|
||||
else if (cos_theta < -1.0 + F_APPROXIMATELY_ZERO)
|
||||
{
|
||||
// a and b are anti-parallel.
|
||||
// Rotate 180 degrees around some orthogonal axis.
|
||||
// Find the projection of the x-axis onto a, and try
|
||||
// using the vector between the projection and the x-axis
|
||||
// as the orthogonal axis.
|
||||
LLVector3 proj = vec_a.mV[VX] / (vec_a * vec_a) * vec_a;
|
||||
LLVector3 ortho_axis(1.f, 0.f, 0.f);
|
||||
ortho_axis -= proj;
|
||||
|
||||
// Turn this into an orthonormal axis.
|
||||
F32 ortho_length = ortho_axis.normalize();
|
||||
// If the axis' length is 0, then our guess at an orthogonal axis
|
||||
// was wrong (a is parallel to the x-axis).
|
||||
if (ortho_length < F_APPROXIMATELY_ZERO)
|
||||
if (cc > 0.0f) // test if the arguments are (anti)parallel
|
||||
{
|
||||
// Use the z-axis instead.
|
||||
ortho_axis.setVec(0.f, 0.f, 1.f);
|
||||
F32 s = sqrtf(ab * ab + cc) + ab; // note: don't try to optimize this line
|
||||
F32 m = 1.0f / sqrtf(cc + s * s); // the inverted magnitude of the quaternion
|
||||
mQ[VX] = c.mV[VX] * m;
|
||||
mQ[VY] = c.mV[VY] * m;
|
||||
mQ[VZ] = c.mV[VZ] * m;
|
||||
mQ[VW] = s * m;
|
||||
return;
|
||||
}
|
||||
if (ab < 0.0f) // test if the angle is bigger than PI/2 (anti parallel)
|
||||
{
|
||||
c = a - b; // the arguments are anti-parallel, we have to choose an axis
|
||||
F32 m = sqrtf(c.mV[VX] * c.mV[VX] + c.mV[VY] * c.mV[VY]); // the length projected on the XY-plane
|
||||
if (m > FP_MAG_THRESHOLD)
|
||||
{
|
||||
mQ[VX] = -c.mV[VY] / m; // return the quaternion with the axis in the XY-plane
|
||||
mQ[VY] = c.mV[VX] / m;
|
||||
mQ[VZ] = 0.0f;
|
||||
mQ[VW] = 0.0f;
|
||||
return;
|
||||
}
|
||||
else // the vectors are parallel to the Z-axis
|
||||
{
|
||||
mQ[VX] = 1.0f; // rotate around the X-axis
|
||||
mQ[VY] = 0.0f;
|
||||
mQ[VZ] = 0.0f;
|
||||
mQ[VW] = 0.0f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct a quaternion from this orthonormal axis.
|
||||
mQ[VX] = ortho_axis.mV[VX];
|
||||
mQ[VY] = ortho_axis.mV[VY];
|
||||
mQ[VZ] = ortho_axis.mV[VZ];
|
||||
mQ[VW] = 0.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// a and b are NOT parallel or anti-parallel.
|
||||
// Return the rotation between these vectors.
|
||||
F32 theta = (F32)acos(cos_theta);
|
||||
|
||||
setAngleAxis(theta, axis);
|
||||
}
|
||||
loadIdentity();
|
||||
}
|
||||
|
||||
// constrains rotation to a cone angle specified in radians
|
||||
@@ -844,79 +836,82 @@ LLQuaternion::Order StringToOrder( const char *str )
|
||||
|
||||
void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const
|
||||
{
|
||||
F32 cos_a = mQ[VW];
|
||||
if (cos_a > 1.0f) cos_a = 1.0f;
|
||||
if (cos_a < -1.0f) cos_a = -1.0f;
|
||||
|
||||
F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a );
|
||||
|
||||
if ( fabs( sin_a ) < 0.0005f )
|
||||
sin_a = 1.0f;
|
||||
else
|
||||
sin_a = 1.f/sin_a;
|
||||
|
||||
F32 temp_angle = 2.0f * (F32) acos( cos_a );
|
||||
if (temp_angle > F_PI)
|
||||
F32 v = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ]); // length of the vector-component
|
||||
if (v > FP_MAG_THRESHOLD)
|
||||
{
|
||||
// The (angle,axis) pair should never have angles outside [PI, -PI]
|
||||
// since we want the _shortest_ (angle,axis) solution.
|
||||
// Since acos is defined for [0, PI], and we multiply by 2.0, we
|
||||
// can push the angle outside the acceptible range.
|
||||
// When this happens we set the angle to the other portion of a
|
||||
// full 2PI rotation, and negate the axis, which reverses the
|
||||
// direction of the rotation (by the right-hand rule).
|
||||
*angle = 2.f * F_PI - temp_angle;
|
||||
vec.mV[VX] = - mQ[VX] * sin_a;
|
||||
vec.mV[VY] = - mQ[VY] * sin_a;
|
||||
vec.mV[VZ] = - mQ[VZ] * sin_a;
|
||||
F32 oomag = 1.0f / v;
|
||||
F32 w = mQ[VW];
|
||||
if (mQ[VW] < 0.0f)
|
||||
{
|
||||
w = -w; // make VW positive
|
||||
oomag = -oomag; // invert the axis
|
||||
}
|
||||
vec.mV[VX] = mQ[VX] * oomag; // normalize the axis
|
||||
vec.mV[VY] = mQ[VY] * oomag;
|
||||
vec.mV[VZ] = mQ[VZ] * oomag;
|
||||
*angle = 2.0f * atan2f(v, w); // get the angle
|
||||
}
|
||||
else
|
||||
{
|
||||
*angle = temp_angle;
|
||||
vec.mV[VX] = mQ[VX] * sin_a;
|
||||
vec.mV[VY] = mQ[VY] * sin_a;
|
||||
vec.mV[VZ] = mQ[VZ] * sin_a;
|
||||
*angle = 0.0f; // no rotation
|
||||
vec.mV[VX] = 0.0f; // around some dummy axis
|
||||
vec.mV[VY] = 0.0f;
|
||||
vec.mV[VZ] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// quaternion does not need to be normalized
|
||||
void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const
|
||||
{
|
||||
LLMatrix3 rot_mat(*this);
|
||||
rot_mat.orthogonalize();
|
||||
rot_mat.getEulerAngles(roll, pitch, yaw);
|
||||
|
||||
// // NOTE: LLQuaternion's are actually inverted with respect to
|
||||
// // the matrices, so this code also assumes inverted quaternions
|
||||
// // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied
|
||||
// // in reverse order (yaw,pitch,roll).
|
||||
// F32 x = -mQ[VX], y = -mQ[VY], z = -mQ[VZ], w = mQ[VW];
|
||||
// F64 m20 = 2.0*(x*z-y*w);
|
||||
// if (1.0f - fabsf(m20) < F_APPROXIMATELY_ZERO)
|
||||
// {
|
||||
// *roll = 0.0f;
|
||||
// *pitch = (F32)asin(m20);
|
||||
// *yaw = (F32)atan2(2.0*(x*y-z*w), 1.0 - 2.0*(x*x+z*z));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// *roll = (F32)atan2(-2.0*(y*z+x*w), 1.0-2.0*(x*x+y*y));
|
||||
// *pitch = (F32)asin(m20);
|
||||
// *yaw = (F32)atan2(-2.0*(x*y+z*w), 1.0-2.0*(y*y+z*z));
|
||||
// }
|
||||
F32 sx = 2 * (mQ[VX] * mQ[VW] - mQ[VY] * mQ[VZ]); // sine of the roll
|
||||
F32 sy = 2 * (mQ[VY] * mQ[VW] + mQ[VX] * mQ[VZ]); // sine of the pitch
|
||||
F32 ys = mQ[VW] * mQ[VW] - mQ[VY] * mQ[VY]; // intermediate cosine 1
|
||||
F32 xz = mQ[VX] * mQ[VX] - mQ[VZ] * mQ[VZ]; // intermediate cosine 2
|
||||
F32 cx = ys - xz; // cosine of the roll
|
||||
F32 cy = sqrtf(sx * sx + cx * cx); // cosine of the pitch
|
||||
if (cy > GIMBAL_THRESHOLD) // no gimbal lock
|
||||
{
|
||||
*roll = atan2f(sx, cx);
|
||||
*pitch = atan2f(sy, cy);
|
||||
*yaw = atan2f(2 * (mQ[VZ] * mQ[VW] - mQ[VX] * mQ[VY]), ys + xz);
|
||||
}
|
||||
else // gimbal lock
|
||||
{
|
||||
if (sy > 0)
|
||||
{
|
||||
*pitch = F_PI_BY_TWO;
|
||||
*yaw = 2 * atan2f(mQ[VZ] + mQ[VX], mQ[VW] + mQ[VY]);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pitch = -F_PI_BY_TWO;
|
||||
*yaw = 2 * atan2f(mQ[VZ] - mQ[VX], mQ[VW] - mQ[VY]);
|
||||
}
|
||||
*roll = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Saves space by using the fact that our quaternions are normalized
|
||||
LLVector3 LLQuaternion::packToVector3() const
|
||||
{
|
||||
F32 x = mQ[VX];
|
||||
F32 y = mQ[VY];
|
||||
F32 z = mQ[VZ];
|
||||
F32 w = mQ[VW];
|
||||
F32 mag = sqrtf(x * x + y * y + z * z + w * w);
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag; // no need to normalize w, it's not used
|
||||
}
|
||||
if( mQ[VW] >= 0 )
|
||||
{
|
||||
return LLVector3( mQ[VX], mQ[VY], mQ[VZ] );
|
||||
return LLVector3( x, y , z );
|
||||
}
|
||||
else
|
||||
{
|
||||
return LLVector3( -mQ[VX], -mQ[VY], -mQ[VZ] );
|
||||
return LLVector3( -x, -y, -z );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llquaternion.h
|
||||
* @brief LLQuaternion class header file.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2000-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -310,43 +304,29 @@ inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q)
|
||||
return (*this);
|
||||
}
|
||||
|
||||
// There may be a cheaper way that avoids the sqrt.
|
||||
// Does sin_a = VX*VX + VY*VY + VZ*VZ?
|
||||
// Copied from Matrix and Quaternion FAQ 1.12
|
||||
inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const
|
||||
{
|
||||
F32 cos_a = mQ[VW];
|
||||
if (cos_a > 1.0f) cos_a = 1.0f;
|
||||
if (cos_a < -1.0f) cos_a = -1.0f;
|
||||
|
||||
F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a );
|
||||
|
||||
if ( fabs( sin_a ) < 0.0005f )
|
||||
sin_a = 1.0f;
|
||||
else
|
||||
sin_a = 1.f/sin_a;
|
||||
|
||||
F32 temp_angle = 2.0f * (F32) acos( cos_a );
|
||||
if (temp_angle > F_PI)
|
||||
F32 v = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ]); // length of the vector-component
|
||||
if (v > FP_MAG_THRESHOLD)
|
||||
{
|
||||
// The (angle,axis) pair should never have angles outside [PI, -PI]
|
||||
// since we want the _shortest_ (angle,axis) solution.
|
||||
// Since acos is defined for [0, PI], and we multiply by 2.0, we
|
||||
// can push the angle outside the acceptible range.
|
||||
// When this happens we set the angle to the other portion of a
|
||||
// full 2PI rotation, and negate the axis, which reverses the
|
||||
// direction of the rotation (by the right-hand rule).
|
||||
*angle = 2.f * F_PI - temp_angle;
|
||||
*x = - mQ[VX] * sin_a;
|
||||
*y = - mQ[VY] * sin_a;
|
||||
*z = - mQ[VZ] * sin_a;
|
||||
F32 oomag = 1.0f / v;
|
||||
F32 w = mQ[VW];
|
||||
if (w < 0.0f)
|
||||
{
|
||||
w = -w; // make VW positive
|
||||
oomag = -oomag; // invert the axis
|
||||
}
|
||||
*x = mQ[VX] * oomag; // normalize the axis
|
||||
*y = mQ[VY] * oomag;
|
||||
*z = mQ[VZ] * oomag;
|
||||
*angle = 2.0f * atan2f(v, w); // get the angle
|
||||
}
|
||||
else
|
||||
{
|
||||
*angle = temp_angle;
|
||||
*x = mQ[VX] * sin_a;
|
||||
*y = mQ[VY] * sin_a;
|
||||
*z = mQ[VZ] * sin_a;
|
||||
*angle = 0.0f; // no rotation
|
||||
*x = 0.0f; // around some dummy axis
|
||||
*y = 0.0f;
|
||||
*z = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user