Compare commits
554
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b0ba10b0b | ||
|
|
9f9c4cf32c | ||
|
|
536ebf604f | ||
|
|
03a616b737 | ||
|
|
0b05f67114 | ||
|
|
0ede690580 | ||
|
|
d81545a871 | ||
|
|
1cda1fc201 | ||
|
|
490dad7838 | ||
|
|
13ecbb8bce | ||
|
|
3346bfc9a8 | ||
|
|
c5de65f115 | ||
|
|
4fffcf9975 | ||
|
|
8962d9b293 | ||
|
|
050c1560e8 | ||
|
|
68b3041f50 | ||
|
|
1ddd153399 | ||
|
|
df0a60caae | ||
|
|
675c86582d | ||
|
|
e6d01ed1a3 | ||
|
|
d8d1064e05 | ||
|
|
5d04cb81ba | ||
|
|
5d5906e980 | ||
|
|
2e7b862ad3 | ||
|
|
ad86e22824 | ||
|
|
536b8a213b | ||
|
|
2e13877926 | ||
|
|
967d63dec4 | ||
|
|
573c4268b6 | ||
|
|
f19e83dcf1 | ||
|
|
caabe8fc87 | ||
|
|
7c4e5309fc | ||
|
|
542124e90c | ||
|
|
e0d02be0f5 | ||
|
|
461e6d1b5b | ||
|
|
d767e6d7eb | ||
|
|
bff1584012 | ||
|
|
3d91a11b95 | ||
|
|
1349b46a8c | ||
|
|
74330ba1dd | ||
|
|
64ab227f62 | ||
|
|
1c51fbd1b4 | ||
|
|
4c2dd553f2 | ||
|
|
2fb985afa4 | ||
|
|
44c93d5074 | ||
|
|
dcf07a46aa | ||
|
|
284a9e0612 | ||
|
|
60349a8690 | ||
|
|
64072be83c | ||
|
|
229abb8412 | ||
|
|
7b1d1fd288 | ||
|
|
1ca1f6ad22 | ||
|
|
0ad66f4bc4 | ||
|
|
d5757c4fb8 | ||
|
|
7fe40bce86 | ||
|
|
5da3d64ede | ||
|
|
2e93b06ac0 | ||
|
|
1e6aa4b40f | ||
|
|
262383395d | ||
|
|
127226c421 | ||
|
|
fabcb021cb | ||
|
|
60ab1ab83e | ||
|
|
1f37095087 | ||
|
|
93c2f70b64 | ||
|
|
b0562df6bb | ||
|
|
65d6a5c774 | ||
|
|
650af0f7b0 | ||
|
|
cf9de25c25 | ||
|
|
fc4009aa50 | ||
|
|
d04cf4d897 | ||
|
|
2e45c67ef2 | ||
|
|
b6d8e1f842 | ||
|
|
284bc364fe | ||
|
|
a050654b4c | ||
|
|
7311dae483 | ||
|
|
c57c3cd1d3 | ||
|
|
3ec5e85485 | ||
|
|
ff95af0367 | ||
|
|
aa9c7d5435 | ||
|
|
dcc9f33357 | ||
|
|
1ace645505 | ||
|
|
dc2b87dce1 | ||
|
|
8e47f5d494 | ||
|
|
333d381f41 | ||
|
|
f9b064cc19 | ||
|
|
116a6c1b2e | ||
|
|
c4506b8e6c | ||
|
|
6786a7be4a | ||
|
|
bb370a304d | ||
|
|
fdcf53c688 | ||
|
|
d3f575547c | ||
|
|
68797e51c6 | ||
|
|
c76c55cdee | ||
|
|
f529ec3018 | ||
|
|
ad667be0d7 | ||
|
|
133fa09261 | ||
|
|
acf19cebf8 | ||
|
|
5dfa4c0840 | ||
|
|
f918602f58 | ||
|
|
2cf2dd24a4 | ||
|
|
eefb069d08 | ||
|
|
3dcffc7df8 | ||
|
|
b121277142 | ||
|
|
d283fcf7b4 | ||
|
|
e7f151ad02 | ||
|
|
0710b781d3 | ||
|
|
7c01ad6917 | ||
|
|
56d2f06631 | ||
|
|
9e47911b19 | ||
|
|
ef80497fbe | ||
|
|
e22cf106c2 | ||
|
|
5ffb270ec1 | ||
|
|
f85f3b0f25 | ||
|
|
e7ec83d626 | ||
|
|
11479cd8c3 | ||
|
|
176e760de1 | ||
|
|
430c60ed1a | ||
|
|
dfea3623f6 | ||
|
|
b38783e4cb | ||
|
|
9382a4c21b | ||
|
|
3cd4c5566f | ||
|
|
601c0977df | ||
|
|
c56f036bab | ||
|
|
44dd50c0ef | ||
|
|
56919ae45f | ||
|
|
6c14e7127d | ||
|
|
578af00b0d | ||
|
|
d6c0bf69b6 | ||
|
|
e8884b4ec0 | ||
|
|
5e79609955 | ||
|
|
4950c96f1c | ||
|
|
51b0cf535e | ||
|
|
4cc17a7f6e | ||
|
|
dca07c5634 | ||
|
|
fd42294faf | ||
|
|
c1246e8c4e | ||
|
|
59fc902cfb | ||
|
|
1fe9755d01 | ||
|
|
1da09a4706 | ||
|
|
f3c591469b | ||
|
|
b1200f9f59 | ||
|
|
47617d6c04 | ||
|
|
4794ab6095 | ||
|
|
bc85767f19 | ||
|
|
e37c218c2a | ||
|
|
a0aaa23904 | ||
|
|
27a6c72091 | ||
|
|
2dcc66f03e | ||
|
|
d70a05a088 | ||
|
|
c2317edf8a | ||
|
|
cb7ac404d9 | ||
|
|
5abc6c995f | ||
|
|
0f21c39e49 | ||
|
|
f6513127ce | ||
|
|
ddd72b2b37 | ||
|
|
7f5df1fb66 | ||
|
|
2e71b64de1 | ||
|
|
45f1f9263f | ||
|
|
878288f06a | ||
|
|
406cdf8d16 | ||
|
|
5b28b024ae | ||
|
|
7c693d8107 | ||
|
|
b8a6d1ac4d | ||
|
|
40533f50df | ||
|
|
539ced191b | ||
|
|
1a400b890b | ||
|
|
ebe5a5579c | ||
|
|
afb18ca75b | ||
|
|
01c62932bd | ||
|
|
6cd8db7b28 | ||
|
|
bb46d91bc6 | ||
|
|
3cd5322496 | ||
|
|
cadecdcab7 | ||
|
|
cd4030b7db | ||
|
|
0a2264cad4 | ||
|
|
bb2a02daa8 | ||
|
|
5991195062 | ||
|
|
54c4055af3 | ||
|
|
cb07210bc7 | ||
|
|
3e40d624a8 | ||
|
|
63ce675914 | ||
|
|
14e5e87a4d | ||
|
|
e7e81c6639 | ||
|
|
23d0601d82 | ||
|
|
6db9138eeb | ||
|
|
6a7c200002 | ||
|
|
e3f70b7125 | ||
|
|
a25e859fa7 | ||
|
|
5b2af1f6b3 | ||
|
|
59df72c4b0 | ||
|
|
4e2eb2f24c | ||
|
|
b905f4b8aa | ||
|
|
fefe87ed1e | ||
|
|
b66905c2f6 | ||
|
|
39472e4d81 | ||
|
|
85fba1325a | ||
|
|
0f39f05fa1 | ||
|
|
8d551c2664 | ||
|
|
346a22f684 | ||
|
|
b1571e4437 | ||
|
|
5ac2abe3ab | ||
|
|
5b15426cc6 | ||
|
|
1ac944b7c1 | ||
|
|
fd90dbb123 | ||
|
|
6ccad91537 | ||
|
|
c89db53ebf | ||
|
|
4ffd70a42a | ||
|
|
bbeb48a60d | ||
|
|
aefe9bc116 | ||
|
|
bcb95f647d | ||
|
|
145a7fa146 | ||
|
|
06f0b6030a | ||
|
|
191ee3a0ed | ||
|
|
f6358694ae | ||
|
|
af14d65a98 | ||
|
|
9fe75dc521 | ||
|
|
0051bea034 | ||
|
|
76c79dba8e | ||
|
|
84dc82506a | ||
|
|
ae1625734c | ||
|
|
e2ce4c0fa9 | ||
|
|
a06a15e769 | ||
|
|
7c5de29b61 | ||
|
|
5f9befebae | ||
|
|
6a7b885891 | ||
|
|
cd8e7bbdca | ||
|
|
5d731ad8c3 | ||
|
|
7964270929 | ||
|
|
ea513d392e | ||
|
|
feba9024eb | ||
|
|
b3e16ce8e0 | ||
|
|
31dd77c694 | ||
|
|
ae58f89fbf | ||
|
|
b3bc36b253 | ||
|
|
7287509fef | ||
|
|
b1c49045a8 | ||
|
|
0d5634475c | ||
|
|
e6bfe7d40c | ||
|
|
811cd0653f | ||
|
|
e2b8a21ff5 | ||
|
|
24c7941f65 | ||
|
|
600a9ee4c5 | ||
|
|
fdfdfedf01 | ||
|
|
a67688322d | ||
|
|
6fe057e277 | ||
|
|
f23e8bfb02 | ||
|
|
eab9da98f2 | ||
|
|
f161992836 | ||
|
|
40e13b91fe | ||
|
|
af6824605b | ||
|
|
babf58f8d2 | ||
|
|
968f5d7693 | ||
|
|
4cc6bd69ae | ||
|
|
199437e859 | ||
|
|
e5fac0a01d | ||
|
|
5d14b84969 | ||
|
|
bcccd06cee | ||
|
|
6b0ab9a49a | ||
|
|
023002ae73 | ||
|
|
579d384c04 | ||
|
|
e2e1524454 | ||
|
|
4a5853c1c2 | ||
|
|
64756d14d0 | ||
|
|
bac2ef601d | ||
|
|
cf3bab89f9 | ||
|
|
dfe41ad984 | ||
|
|
b784bebaa9 | ||
|
|
bcf727cf58 | ||
|
|
ecd0a53412 | ||
|
|
3456434e37 | ||
|
|
454c5b1ed2 | ||
|
|
dc2c437a1a | ||
|
|
819d3f5ded | ||
|
|
4f802689f2 | ||
|
|
9cbbe55598 | ||
|
|
7e2dafdcb8 | ||
|
|
c7873d68f7 | ||
|
|
939ec526a8 | ||
|
|
b20a635db0 | ||
|
|
a656bee0df | ||
|
|
42f07e3f14 | ||
|
|
5803b05bd5 | ||
|
|
ccf0ba50c4 | ||
|
|
f3bc977d32 | ||
|
|
80609e0816 | ||
|
|
795d481ca6 | ||
|
|
1b936b9af8 | ||
|
|
f141cc28b0 | ||
|
|
4cb64b58be | ||
|
|
028af34d3d | ||
|
|
ce54997be5 | ||
|
|
3d213fa713 | ||
|
|
e71f3790ce | ||
|
|
67b9cba4d3 | ||
|
|
78a471f684 | ||
|
|
d4289c5d54 | ||
|
|
0c17c5440a | ||
|
|
c4116da564 | ||
|
|
d0821953bb | ||
|
|
e782adef94 | ||
|
|
d3572c2562 | ||
|
|
1f3838b155 | ||
|
|
6aa459073e | ||
|
|
0932c33185 | ||
|
|
5e542aa841 | ||
|
|
6d53abd5af | ||
|
|
3ea58bf8db | ||
|
|
71a4c2c3d2 | ||
|
|
a3e391a523 | ||
|
|
9cb15b302c | ||
|
|
15c1a28d37 | ||
|
|
d3a500e54e | ||
|
|
a0a5eb8aef | ||
|
|
a92955eade | ||
|
|
f043f3d4f9 | ||
|
|
992a057a1b | ||
|
|
07da1e7e1a | ||
|
|
2c07222ef6 | ||
|
|
918e315d47 | ||
|
|
c824731bc6 | ||
|
|
0c39caa622 | ||
|
|
1f1e28baf8 | ||
|
|
0c303389d6 | ||
|
|
01a896ef5b | ||
|
|
0e5e760135 | ||
|
|
7e7d877874 | ||
|
|
57ccb6fd6b | ||
|
|
efa2876e29 | ||
|
|
59ef7d8fd1 | ||
|
|
1f308c9ec3 | ||
|
|
4943d3aa53 | ||
|
|
828d561113 | ||
|
|
fcf72a7123 | ||
|
|
d3f5bc6e2d | ||
|
|
f525a05be8 | ||
|
|
fc7ec4299e | ||
|
|
21d053b1b6 | ||
|
|
68e64a5aa7 | ||
|
|
8e718fe288 | ||
|
|
efec9070e1 | ||
|
|
e3646d4d4a | ||
|
|
4219f16f61 | ||
|
|
c3b1802e95 | ||
|
|
40fe078021 | ||
|
|
a5a6600e74 | ||
|
|
03b9303f22 | ||
|
|
b5a59ea6f9 | ||
|
|
c6b2124129 | ||
|
|
d320a6facb | ||
|
|
0793c2cb8c | ||
|
|
d14755abb8 | ||
|
|
abd4aa2e6b | ||
|
|
58417e78e5 | ||
|
|
390eb1c6e9 | ||
|
|
d4c6530a72 | ||
|
|
ff17b44a41 | ||
|
|
5bd2d47571 | ||
|
|
f8e475cd34 | ||
|
|
a05e063949 | ||
|
|
eb06a90109 | ||
|
|
e2f6632fee | ||
|
|
5c5c583dcc | ||
|
|
0d8d5c02d0 | ||
|
|
382e0c6ad2 | ||
|
|
a8d1c44408 | ||
|
|
78b4318c34 | ||
|
|
b47031a099 | ||
|
|
0f7b65a921 | ||
|
|
33f7903aeb | ||
|
|
f3c2740917 | ||
|
|
09a57c7a52 | ||
|
|
9068f0606e | ||
|
|
c577b7e369 | ||
|
|
5850464ba7 | ||
|
|
50e240d5e4 | ||
|
|
75c2a45b25 | ||
|
|
c958d63897 | ||
|
|
b633b8d0d3 | ||
|
|
76948416a9 | ||
|
|
f4a527c57c | ||
|
|
c491baff0e | ||
|
|
6d05fc6f57 | ||
|
|
ca53add820 | ||
|
|
6fe3099ab4 | ||
|
|
a34eceb327 | ||
|
|
c9042c3186 | ||
|
|
b46fe0d51c | ||
|
|
6d1d3173fe | ||
|
|
030d044d03 | ||
|
|
29fb8e0f74 | ||
|
|
6e326976d5 | ||
|
|
03a7d72a62 | ||
|
|
f913febd71 | ||
|
|
daa0fbdc6b | ||
|
|
d4c52b599d | ||
|
|
ec88373eb7 | ||
|
|
4286cafdeb | ||
|
|
3880d8e2f2 | ||
|
|
671c84ad44 | ||
|
|
a0d687bb24 | ||
|
|
704385ff0a | ||
|
|
81a657edec | ||
|
|
9d0bad29c0 | ||
|
|
2fb8e32104 | ||
|
|
c522e499b2 | ||
|
|
4700955480 | ||
|
|
2c66081fa4 | ||
|
|
855e88da43 | ||
|
|
ad302db9a8 | ||
|
|
bfa5fff500 | ||
|
|
01c64fd554 | ||
|
|
13a2b92a32 | ||
|
|
29e79f8f61 | ||
|
|
8f7527ede0 | ||
|
|
7cd149a4d8 | ||
|
|
e45912fd8a | ||
|
|
56c4ba67c6 | ||
|
|
7e7ce2f38e | ||
|
|
7dc9eba2d0 | ||
|
|
f91d96b51a | ||
|
|
bc19609147 | ||
|
|
1ccaf3a0bd | ||
|
|
03bfd829da | ||
|
|
e1f7a1e0a0 | ||
|
|
ceeac0ecf0 | ||
|
|
c9d0eac739 | ||
|
|
8f24d924ee | ||
|
|
8537cc9edf | ||
|
|
58f3985567 | ||
|
|
872db67f21 | ||
|
|
006f90997a | ||
|
|
26b4776394 | ||
|
|
66c64459e6 | ||
|
|
dc8657f57f | ||
|
|
9d647b90e0 | ||
|
|
f5730c950b | ||
|
|
15d37daebd | ||
|
|
795c9876af | ||
|
|
45f653167d | ||
|
|
403d9b6ac1 | ||
|
|
722af5f659 | ||
|
|
471b9f02ec | ||
|
|
fd294b6f98 | ||
|
|
88baaa72be | ||
|
|
61084cf1ba | ||
|
|
5b63f0755a | ||
|
|
9eb5cf6c98 | ||
|
|
679db5a22b | ||
|
|
0e35168bdb | ||
|
|
035dcc7ab7 | ||
|
|
252deed5b9 | ||
|
|
c2c4cad753 | ||
|
|
42e76477cf | ||
|
|
1eade74e5a | ||
|
|
f1f0fa0aa9 | ||
|
|
deef158822 | ||
|
|
fef2006663 | ||
|
|
5c97fd576a | ||
|
|
c4eb6b7b65 | ||
|
|
31324761cc | ||
|
|
e495f03ee9 | ||
|
|
f5769627e4 | ||
|
|
06ad73f85b | ||
|
|
fa20363853 | ||
|
|
2564432e71 | ||
|
|
addf47600d | ||
|
|
7f534a7966 | ||
|
|
eabffece1f | ||
|
|
afed842ad1 | ||
|
|
c46cfb5d47 | ||
|
|
34fe42bbd9 | ||
|
|
0c1d96b749 | ||
|
|
9b67f52d56 | ||
|
|
d37907d35d | ||
|
|
fee8d0cf78 | ||
|
|
f5f9c6b81f | ||
|
|
4e3460a34b | ||
|
|
8545b6ce6b | ||
|
|
e417903c23 | ||
|
|
81eae3fa48 | ||
|
|
90c58087e8 | ||
|
|
19bc1e6313 | ||
|
|
4a4e8c87b8 | ||
|
|
f04e559dc2 | ||
|
|
8e5e657344 | ||
|
|
a4f1f62068 | ||
|
|
a3e279f06f | ||
|
|
d11954e80c | ||
|
|
812170ebce | ||
|
|
fdd3c77298 | ||
|
|
342de209a2 | ||
|
|
caeb32488e | ||
|
|
ff7e70f4d5 | ||
|
|
950f51909c | ||
|
|
f86e6d344c | ||
|
|
08581282dd | ||
|
|
e1e47e76ec | ||
|
|
3ff059848c | ||
|
|
22c7df5936 | ||
|
|
81a44d1340 | ||
|
|
2c089e6166 | ||
|
|
589dae7b0c | ||
|
|
3ff13189aa | ||
|
|
7151c3fac1 | ||
|
|
3e023b77dd | ||
|
|
e3fc89890c | ||
|
|
ce2a6cfe5c | ||
|
|
31d9eaf54c | ||
|
|
781c445d14 | ||
|
|
26a416399f | ||
|
|
f7dc7f039e | ||
|
|
3c74fea087 | ||
|
|
be0635bfd3 | ||
|
|
6723ef95c2 | ||
|
|
1a8fd62680 | ||
|
|
8b57ed46b1 | ||
|
|
25c08e56c2 | ||
|
|
0f148b6ab6 | ||
|
|
47575fe357 | ||
|
|
7c14453b5a | ||
|
|
a47d5536fa | ||
|
|
db8f7f21e8 | ||
|
|
3c312c55f1 | ||
|
|
2d11419cba | ||
|
|
07a4508944 | ||
|
|
62913739bb | ||
|
|
55e9d8d944 | ||
|
|
a9439d58c7 | ||
|
|
800ad40c4c | ||
|
|
62864637a3 | ||
|
|
4d4ac7ea24 | ||
|
|
119651482d | ||
|
|
ecf0a1a736 | ||
|
|
94942d1ac4 | ||
|
|
b0a5b54949 | ||
|
|
ac57eab8ac | ||
|
|
74a4144193 | ||
|
|
5c44cb0f01 | ||
|
|
c044d711ef | ||
|
|
f2132f6a7d | ||
|
|
69871b15ff | ||
|
|
f4ec02a592 | ||
|
|
53f7743678 | ||
|
|
15893bc558 | ||
|
|
73b974f1b5 | ||
|
|
0e7bdc208b | ||
|
|
e0a07b7a92 | ||
|
|
4da58e8846 | ||
|
|
966b9e5c2b | ||
|
|
1625192c81 | ||
|
|
c5e8c6603c | ||
|
|
37e541d326 | ||
|
|
862a827fe6 | ||
|
|
b96c5c9e4b |
@@ -22,7 +22,7 @@ PROJECT_NAME = SimGear
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 1.99.5
|
||||
PROJECT_NUMBER = 1.9.0
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
||||
+1
-4
@@ -2,14 +2,11 @@ EXTRA_DIST = \
|
||||
acinclude.m4 \
|
||||
autogen.sh \
|
||||
DoxygenMain.cxx \
|
||||
README.MSVC \
|
||||
README.zlib \
|
||||
README.plib \
|
||||
README.OpenAL \
|
||||
README.OSG \
|
||||
projects \
|
||||
SimGear.dsp \
|
||||
SimGear.dsw
|
||||
projects
|
||||
|
||||
SUBDIRS = simgear
|
||||
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
Version 1.99.5
|
||||
* October 30, 2008 (sourcecode snapshot release)
|
||||
Version 1.9.0
|
||||
* Thu Dec 18 15:12:15 CST 2008
|
||||
|
||||
|
||||
Version 1.8.6
|
||||
* Mon Dec 1 14:02:47 CST 2008
|
||||
|
||||
|
||||
Version 1.8.5
|
||||
* October 30, 2008 (source code snapshot release)
|
||||
|
||||
|
||||
New in 0.3.10
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
This document describes how to build SimGear using the supplied workspace and
|
||||
project files.
|
||||
|
||||
Unpack the SimGear source file into your work directory. This creates a new
|
||||
subdirectory called SimGear-X.Y.Z. Rename this to SimGear. Before we can
|
||||
build SimGear you must unpack and build the third party libraries metakit and
|
||||
zlib. Sources for these are included in the SimGear/src-libs directory.
|
||||
Unpack these into the top level SimGear directory. At this point your
|
||||
directory structure should look something like this:
|
||||
|
||||
<work_dir>/
|
||||
SimGear/
|
||||
metakit-x.y.z/
|
||||
simgear/
|
||||
src-libs/
|
||||
zlib-x.y.z/
|
||||
|
||||
Now open the SimGear workspace. This workspace file contains projects for
|
||||
building metakit(mklib), SimGear and zlib. Select each project as the active
|
||||
project and build all. Order is unimportant since there are no dependencies
|
||||
between the projects.
|
||||
|
||||
The workspace and project files are generated by a perl script with extra
|
||||
input from the am2dsp.cfg file.
|
||||
+5
-2
@@ -3,16 +3,19 @@
|
||||
You *must* have OpenSceneGraph (OSG) installed to build this version of
|
||||
FlightGear.
|
||||
|
||||
Notice that FlightGear 1.9.0 requires at least version 2.7.8. Using earlier
|
||||
versions of OSG will yield serious rendering bugs.
|
||||
|
||||
You can get the latest version of OSG from:
|
||||
|
||||
http://www.openscenegraph.org/
|
||||
|
||||
Build notes:
|
||||
|
||||
Unzip the file OpenSceneGraph-2.4.zip and install using the following
|
||||
Unzip the file OpenSceneGraph-x.x.zip and install using the following
|
||||
commands:
|
||||
|
||||
unzip OpenSceneGraph-2.4
|
||||
unzip OpenSceneGraph-x.x
|
||||
cd OpenSceneGraph
|
||||
ccmake .
|
||||
|
||||
|
||||
+10
-10
@@ -3,27 +3,27 @@
|
||||
You *must* have the development components of OpenAL installed on your system
|
||||
to build FlightGear!" You can get a copy here:
|
||||
|
||||
http://www.openal.org
|
||||
http://connect.creativelabs.com/openal/default.aspx
|
||||
|
||||
Build notes:
|
||||
|
||||
You can download a versioned release of the openal library from
|
||||
http://www.openal.org/downloads.html. Download the openal source,
|
||||
release 0.0.8 (dated February 11, 2006) and run:
|
||||
tar xzvf openal-0.0.8.tar.gz
|
||||
cd openal-0.0.8
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
tar xjvf openal-soft-1.5.304.tar.bz2
|
||||
cd openal-soft-1.5.304/
|
||||
ccmake .
|
||||
|
||||
[ While running ccmake: press 'c' to configure, press 'c' once more, and
|
||||
then press 'g' to generate and exit ]
|
||||
|
||||
|
||||
The alut library is also required, but comes separately in the package
|
||||
freelut-1.1.0.tar.gz. This package can be downloaded from the same page
|
||||
(http://www.openal.org/downloads.html). Download and run:
|
||||
(http://connect.creativelabs.com/openal/default.aspx). Download and run:
|
||||
tar xzvf freelut-1.1.0.tar.gz
|
||||
cd freelut-1.1.0
|
||||
cd freealut-1.1.0
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
|
||||
Alternatively, you can use the CVS version (follow the instructions at
|
||||
the OpenAL web site) and build/install that one.
|
||||
|
||||
-2720
File diff suppressed because it is too large
Load Diff
-29
@@ -1,29 +0,0 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "SimGear"=".\SimGear.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
+292
-48
@@ -6,19 +6,25 @@ dnl
|
||||
AC_DEFUN([wi_EXTRA_IDIR], [
|
||||
incdir="$1"
|
||||
if test -r $incdir ; then
|
||||
case "$CPPFLAGS" in
|
||||
*-I${incdir}*)
|
||||
# echo " + already had $incdir" 1>&6
|
||||
;;
|
||||
*)
|
||||
if test "$CPPFLAGS" = "" ; then
|
||||
CPPFLAGS="-I$incdir"
|
||||
else
|
||||
CPPFLAGS="$CPPFLAGS -I$incdir"
|
||||
fi
|
||||
echo " + found $incdir" 1>&6
|
||||
;;
|
||||
esac
|
||||
already=""
|
||||
for CPPflag in $CPPFLAGS ; do
|
||||
if test "_$CPPflag" = "_-I${incdir}" ; then
|
||||
already=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -n "$already" ; then
|
||||
echo " + already had -I$incdir" 1>&AS_MESSAGE_LOG_FD
|
||||
else
|
||||
if test "$CPPFLAGS" = "" ; then
|
||||
CPPFLAGS="-I$incdir"
|
||||
else
|
||||
CPPFLAGS="$CPPFLAGS -I$incdir"
|
||||
fi
|
||||
echo " + added -I$incdir" 1>&AS_MESSAGE_LOG_FD
|
||||
fi
|
||||
else
|
||||
echo " + IDIR is not accessible: '$myincdir'" 1>&AS_MESSAGE_LOG_FD
|
||||
fi
|
||||
])
|
||||
dnl
|
||||
@@ -28,19 +34,25 @@ dnl
|
||||
AC_DEFUN([wi_EXTRA_LDIR], [
|
||||
mylibdir="$1"
|
||||
if test -r $mylibdir ; then
|
||||
case "$LDFLAGS" in
|
||||
*-L${mylibdir}*)
|
||||
# echo " + already had $mylibdir" 1>&6
|
||||
;;
|
||||
*)
|
||||
if test "$LDFLAGS" = "" ; then
|
||||
LDFLAGS="-L$mylibdir"
|
||||
else
|
||||
LDFLAGS="$LDFLAGS -L$mylibdir"
|
||||
fi
|
||||
echo " + found $mylibdir" 1>&6
|
||||
;;
|
||||
esac
|
||||
already=""
|
||||
for LDflag in $LDFLAGS ; do
|
||||
if test "_$LDflag" = "_-L${mylibdir}" ; then
|
||||
already=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -n "$already" ; then
|
||||
echo " + already had -L$mylibdir" 1>&AS_MESSAGE_LOG_FD
|
||||
else
|
||||
if test "$LDFLAGS" = "" ; then
|
||||
LDFLAGS="-L$mylibdir"
|
||||
else
|
||||
LDFLAGS="$LDFLAGS -L$mylibdir"
|
||||
fi
|
||||
echo " + added -L$mylibdir" 1>&AS_MESSAGE_LOG_FD
|
||||
fi
|
||||
else
|
||||
echo " + LDIR is not accessible: '$mylibdir'" 1>&AS_MESSAGE_LOG_FD
|
||||
fi
|
||||
])
|
||||
dnl
|
||||
@@ -50,12 +62,9 @@ dnl
|
||||
AC_DEFUN([wi_EXTRA_PDIR], [
|
||||
progdir="$1"
|
||||
if test -r $progdir ; then
|
||||
case "$PATH" in
|
||||
*:${progdir}*)
|
||||
# echo " + already had $progdir" 1>&6
|
||||
;;
|
||||
*${progdir}:*)
|
||||
# echo " + already had $progdir" 1>&6
|
||||
case ":$PATH:" in
|
||||
*:${progdir}:*)
|
||||
echo " + already had $progdir in \$PATH" 1>&AS_MESSAGE_LOG_FD
|
||||
;;
|
||||
*)
|
||||
if test "$PATH" = "" ; then
|
||||
@@ -63,9 +72,11 @@ if test -r $progdir ; then
|
||||
else
|
||||
PATH="$PATH:$progdir"
|
||||
fi
|
||||
echo " + found $progdir" 1>&6
|
||||
echo " + appended $progdir to \$PATH" 1>&AS_MESSAGE_LOG_FD
|
||||
;;
|
||||
esac
|
||||
else
|
||||
echo " + PDIR is not accessible: '$progdir'" 1>&AS_MESSAGE_LOG_FD
|
||||
fi
|
||||
])
|
||||
dnl
|
||||
@@ -89,23 +100,32 @@ if test "$subexdirs" = "" ; then
|
||||
subexdirs="-"
|
||||
fi
|
||||
for subexdir in $subexdirs ; do
|
||||
if test "$subexdir" = "-" ; then
|
||||
subexdir=""
|
||||
else
|
||||
subexdir="/$subexdir"
|
||||
fi
|
||||
for exdir in $exdirs ; do
|
||||
if test "$exdir" != "/usr" || test "$subexdir" != ""; then
|
||||
incdir="${exdir}/include${subexdir}"
|
||||
wi_EXTRA_IDIR($incdir)
|
||||
if test "$subexdir" = "-" ; then
|
||||
subexdir=""
|
||||
else
|
||||
subexdir="/$subexdir"
|
||||
fi
|
||||
for exdir in $exdirs ; do
|
||||
if test "$exdir" != "/usr" || test "$subexdir" != ""; then
|
||||
incdir="${exdir}/include${subexdir}"
|
||||
wi_EXTRA_IDIR($incdir)
|
||||
|
||||
mylibdir="${exdir}/lib${subexdir}"
|
||||
wi_EXTRA_LDIR($mylibdir)
|
||||
dnl On 64-bit machines, if lib64/ exists and is not identical to lib/
|
||||
dnl then it should be listed here, listed ahead of lib/.
|
||||
mylibdir64="${exdir}/lib64${subexdir}"
|
||||
mylibdir32="${exdir}/lib${subexdir}"
|
||||
|
||||
progdir="${exdir}/bin${subexdir}"
|
||||
wi_EXTRA_PDIR($progdir)
|
||||
fi
|
||||
done
|
||||
if test "x86_64" = $(uname -m) \
|
||||
-a ! ${mylibdir64} -ef ${mylibdir32} ; then
|
||||
wi_EXTRA_LDIR($mylibdir64)
|
||||
fi
|
||||
|
||||
wi_EXTRA_LDIR($mylibdir32)
|
||||
|
||||
progdir="${exdir}/bin${subexdir}"
|
||||
wi_EXTRA_PDIR($progdir)
|
||||
fi
|
||||
done
|
||||
done
|
||||
])
|
||||
dnl
|
||||
@@ -460,3 +480,227 @@ pushdef([AC_PROG_INSTALL],
|
||||
INSTALL_PROGRAM='${INSTALL} $(INSTALL_STRIP_FLAG)'
|
||||
INSTALL_SCRIPT='${INSTALL}'
|
||||
])dnl
|
||||
|
||||
# ===========================================================================
|
||||
# http://autoconf-archive.cryp.to/ax_boost_base.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_BOOST_BASE([MINIMUM-VERSION])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Test for the Boost C++ libraries of a particular version (or newer)
|
||||
#
|
||||
# If no path to the installed boost library is given the macro searchs
|
||||
# under /usr, /usr/local, /opt and /opt/local and evaluates the
|
||||
# $BOOST_ROOT environment variable. Further documentation is available at
|
||||
# <http://randspringer.de/boost/index.html>.
|
||||
#
|
||||
# This macro calls:
|
||||
#
|
||||
# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
|
||||
#
|
||||
# And sets:
|
||||
#
|
||||
# HAVE_BOOST
|
||||
#
|
||||
# LAST MODIFICATION
|
||||
#
|
||||
# 2008-04-12
|
||||
#
|
||||
# COPYLEFT
|
||||
#
|
||||
# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved.
|
||||
|
||||
AC_DEFUN([AX_BOOST_BASE],
|
||||
[
|
||||
AC_ARG_WITH([boost],
|
||||
AS_HELP_STRING([--with-boost@<:@=DIR@:>@], [use boost (default is yes) - it is possible to specify the root directory for boost (optional)]),
|
||||
[
|
||||
if test "$withval" = "no"; then
|
||||
want_boost="no"
|
||||
elif test "$withval" = "yes"; then
|
||||
want_boost="yes"
|
||||
ac_boost_path=""
|
||||
else
|
||||
want_boost="yes"
|
||||
ac_boost_path="$withval"
|
||||
fi
|
||||
],
|
||||
[want_boost="yes"])
|
||||
|
||||
|
||||
AC_ARG_WITH([boost-libdir],
|
||||
AS_HELP_STRING([--with-boost-libdir=LIB_DIR],
|
||||
[Force given directory for boost libraries. Note that this will overwrite library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]),
|
||||
[
|
||||
if test -d $withval
|
||||
then
|
||||
ac_boost_lib_path="$withval"
|
||||
else
|
||||
AC_MSG_ERROR(--with-boost-libdir expected directory name)
|
||||
fi
|
||||
],
|
||||
[ac_boost_lib_path=""]
|
||||
)
|
||||
|
||||
if test "x$want_boost" = "xyes"; then
|
||||
boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
|
||||
boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
|
||||
boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'`
|
||||
boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
|
||||
boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
|
||||
if test "x$boost_lib_version_req_sub_minor" = "x" ; then
|
||||
boost_lib_version_req_sub_minor="0"
|
||||
fi
|
||||
WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
|
||||
AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
|
||||
succeeded=no
|
||||
|
||||
dnl first we check the system location for boost libraries
|
||||
dnl this location ist chosen if boost libraries are installed with the --layout=system option
|
||||
dnl or if you install boost with RPM
|
||||
if test "$ac_boost_path" != ""; then
|
||||
BOOST_LDFLAGS="-L$ac_boost_path/lib"
|
||||
BOOST_CPPFLAGS="-I$ac_boost_path/include"
|
||||
else
|
||||
for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
|
||||
if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then
|
||||
BOOST_LDFLAGS="-L$ac_boost_path_tmp/lib"
|
||||
BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
dnl overwrite ld flags if we have required special directory with
|
||||
dnl --with-boost-libdir parameter
|
||||
if test "$ac_boost_lib_path" != ""; then
|
||||
BOOST_LDFLAGS="-L$ac_boost_lib_path"
|
||||
fi
|
||||
|
||||
CPPFLAGS_SAVED="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
||||
export CPPFLAGS
|
||||
|
||||
LDFLAGS_SAVED="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
|
||||
export LDFLAGS
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
@%:@include <boost/version.hpp>
|
||||
]], [[
|
||||
#if BOOST_VERSION >= $WANT_BOOST_VERSION
|
||||
// Everything is okay
|
||||
#else
|
||||
# error Boost version is too old
|
||||
#endif
|
||||
]])],[
|
||||
AC_MSG_RESULT(yes)
|
||||
succeeded=yes
|
||||
found_system=yes
|
||||
],[
|
||||
])
|
||||
AC_LANG_POP([C++])
|
||||
|
||||
|
||||
|
||||
dnl if we found no boost with system layout we search for boost libraries
|
||||
dnl built and installed without the --layout=system option or for a staged(not installed) version
|
||||
if test "x$succeeded" != "xyes"; then
|
||||
_version=0
|
||||
if test "$ac_boost_path" != ""; then
|
||||
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
|
||||
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
|
||||
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
|
||||
V_CHECK=`expr $_version_tmp \> $_version`
|
||||
if test "$V_CHECK" = "1" ; then
|
||||
_version=$_version_tmp
|
||||
fi
|
||||
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
|
||||
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
|
||||
done
|
||||
fi
|
||||
else
|
||||
for ac_boost_path in /usr /usr/local /opt /opt/local ; do
|
||||
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
|
||||
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
|
||||
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
|
||||
V_CHECK=`expr $_version_tmp \> $_version`
|
||||
if test "$V_CHECK" = "1" ; then
|
||||
_version=$_version_tmp
|
||||
best_path=$ac_boost_path
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
|
||||
BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
|
||||
if test "$ac_boost_lib_path" = ""
|
||||
then
|
||||
BOOST_LDFLAGS="-L$best_path/lib"
|
||||
fi
|
||||
|
||||
if test "x$BOOST_ROOT" != "x"; then
|
||||
if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/lib" && test -r "$BOOST_ROOT/stage/lib"; then
|
||||
version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'`
|
||||
stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`
|
||||
stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
|
||||
V_CHECK=`expr $stage_version_shorten \>\= $_version`
|
||||
if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then
|
||||
AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
|
||||
BOOST_CPPFLAGS="-I$BOOST_ROOT"
|
||||
BOOST_LDFLAGS="-L$BOOST_ROOT/stage/lib"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
||||
export CPPFLAGS
|
||||
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
|
||||
export LDFLAGS
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
@%:@include <boost/version.hpp>
|
||||
]], [[
|
||||
#if BOOST_VERSION >= $WANT_BOOST_VERSION
|
||||
// Everything is okay
|
||||
#else
|
||||
# error Boost version is too old
|
||||
#endif
|
||||
]])],[
|
||||
AC_MSG_RESULT(yes)
|
||||
succeeded=yes
|
||||
found_system=yes
|
||||
],[
|
||||
])
|
||||
AC_LANG_POP([C++])
|
||||
fi
|
||||
|
||||
if test "$succeeded" != "yes" ; then
|
||||
if test "$_version" = "0" ; then
|
||||
AC_MSG_ERROR([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
|
||||
else
|
||||
AC_MSG_ERROR([Your boost libraries seems to old (version $_version).])
|
||||
fi
|
||||
else
|
||||
AC_SUBST(BOOST_CPPFLAGS)
|
||||
AC_SUBST(BOOST_LDFLAGS)
|
||||
AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS_SAVED"
|
||||
LDFLAGS="$LDFLAGS_SAVED"
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
+164
-9
@@ -8,7 +8,7 @@ dnl Require at least automake 2.52
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
dnl Initialize the automake stuff
|
||||
AM_INIT_AUTOMAKE(SimGear, 1.99.5-rc2)
|
||||
AM_INIT_AUTOMAKE(SimGear, 2.0.0)
|
||||
|
||||
dnl Specify KAI C++ compiler and flags.
|
||||
dnl Borrowed with slight modification from blitz distribution.
|
||||
@@ -34,9 +34,15 @@ AC_PROG_MAKE_SET
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CXXCPP
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AX_BOOST_BASE([1.37.0])
|
||||
|
||||
if test "x$BOOST_CPPFLAGS" != "x-I/usr/include" ; then
|
||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
||||
fi
|
||||
|
||||
dnl set the $host variable based on local machine/os
|
||||
AC_CANONICAL_HOST
|
||||
@@ -121,6 +127,12 @@ if test "x$with_plib" != "x" ; then
|
||||
EXTRA_DIRS="${EXTRA_DIRS} $with_plib"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(plib_framework, [ --with-plib-framework=PREFIX Specify the prefix path to PLIB.framework ])
|
||||
|
||||
if test "x$with_plib_framework" != "x"; then
|
||||
echo "plib framework prefix is $with_plib_framework"
|
||||
fi
|
||||
|
||||
# specify the osg location
|
||||
AC_ARG_WITH(osg, [ --with-osg=PREFIX Specify the prefix path to osg])
|
||||
|
||||
@@ -129,6 +141,21 @@ if test "x$with_osg" != "x" ; then
|
||||
EXTRA_DIRS="${EXTRA_DIRS} $with_osg"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(osg_framework, [ --with-osg-framework=PREFIX Specify the prefix path to OSG.framework ])
|
||||
|
||||
if test "x$with_osg_framework" != "x"; then
|
||||
echo "osg framework prefix is $with_osg_framework"
|
||||
CPPFLAGS = "$CPPFLAGS -F$with-osg-framework"
|
||||
export DYLD_FRAMEWORK_PATH="$DYLD_FRAMEWORK_PATH:$with_osg_framework"
|
||||
fi
|
||||
|
||||
dnl specifying OpenAL.framework (for user provided OpenAL.framework / ALUT)
|
||||
AC_ARG_WITH(openal_framework, [ --with-openal-framework=PREFIX Speicfy the prefix path to OpenAL.framework ])
|
||||
|
||||
if test "x$with_openal_framework" != "x"; then
|
||||
echo "OpenAL framework prefix is $with_openal_framework"
|
||||
fi
|
||||
|
||||
dnl Determine an extra directories to add to include/lib search paths
|
||||
case "${host}" in
|
||||
*-apple-darwin* | *-*-cygwin* | *-*-mingw32*)
|
||||
@@ -198,6 +225,7 @@ LIBS=""
|
||||
|
||||
dnl check for some default libraries
|
||||
AC_SEARCH_LIBS(cos, m)
|
||||
AC_SEARCH_LIBS(clock_gettime, rt)
|
||||
|
||||
base_LIBS="$LIBS"
|
||||
|
||||
@@ -274,7 +302,7 @@ case "${host}" in
|
||||
dnl CygWin under Windoze.
|
||||
INCLUDES="$INCLUDES -I/usr/local/include/"
|
||||
LIBS="$LIBS -L/usr/local/lib"
|
||||
AC_SEARCH_LIBS(alGenBuffers, [ openal32 openal ] )
|
||||
AC_SEARCH_LIBS(alGenBuffers, [ openal32 openal 'openal -ldsound -lwinmm' ] )
|
||||
AC_SEARCH_LIBS(alutInit, [ openal32 ALut alut ] )
|
||||
LIBS="$LIBS -lwinmm -ldsound -ldxguid -lole32"
|
||||
openal_LIBS="$LIBS"
|
||||
@@ -287,9 +315,54 @@ case "${host}" in
|
||||
|
||||
LIBS="$LIBS -framework IOKit -framework OpenAL"
|
||||
openal_LIBS="$LIBS"
|
||||
# not sure how to test if OpenAL exists on MacOS (does it come by default?)
|
||||
OPENAL_OK="yes"
|
||||
ALUT_OK="yes"
|
||||
ALUT_OK="no"
|
||||
|
||||
if test "x$with_openal_lib" != "x"; then
|
||||
echo "libopenal is not supported on Mac OS platform."
|
||||
openal_LIBS=""
|
||||
fi
|
||||
OPENAL_OK="yes"
|
||||
# Looking for alut.h, if found assume that it is a part of
|
||||
# the OpenAL package.
|
||||
AC_CHECK_HEADERS([OpenAL/alut.h],[ALUT_OK="yes"])
|
||||
|
||||
|
||||
dnl Thank you Christian Bauer from SheepSaver
|
||||
dnl Modified by Tatsuhiro Nishioka for accepting a given framework path
|
||||
dnl AC_CHECK_FRAMEWORK($1=NAME, $2=INCLUDES, $3=FRAMEWORK_PATH) ; $3 is optional
|
||||
AC_DEFUN([AC_CHECK_FRAMEWORK], [
|
||||
AS_VAR_PUSHDEF([ac_Framework], [ac_cv_framework_$1])dnl
|
||||
AC_CACHE_CHECK([whether compiler supports framework $1],
|
||||
ac_Framework, [
|
||||
saved_LIBS="$LIBS"
|
||||
FRAMEWORKS="$FRAMEWORKS -framework $1"
|
||||
if test "$3" = ""; then
|
||||
FRAMEWORKS="$FRAMEWORKS $ADD2LD"
|
||||
elif test "`echo $FRAMEWORKS | grep -- -F$3`" = ""; then
|
||||
FRAMEWORKS="$FRAMEWORKS -F$3"
|
||||
CXXFLAGS="$CXXFLAGS -F$3"
|
||||
CCFLAGS="$CCFLAGS -F$3"
|
||||
dnl This is needed for AC_TRY_LINK when a framework path is specified
|
||||
export DYLD_FRAMEWORK_PATH="${DYLD_FRAMEWORK_PATH}:$3"
|
||||
fi
|
||||
AC_TRY_LINK(
|
||||
[$2], [],
|
||||
[AS_VAR_SET(ac_Framework, yes)], [AS_VAR_SET(ac_Framework, no); LIBS="$saved_LIBS"]
|
||||
)
|
||||
])
|
||||
AS_IF([test AS_VAR_GET(ac_Framework) = yes],
|
||||
[AC_DEFINE(AS_TR_CPP(HAVE_FRAMEWORK_$1), 1, [Define if framework $1 is available.])]
|
||||
)
|
||||
AS_VAR_POPDEF([ac_Framework])dnl
|
||||
])
|
||||
|
||||
dnl Check for OpenAL.framework when --with-openal-framework is specified
|
||||
dnl Of cource OpenAL.framework needs to have alut.h
|
||||
if test "x$with_openal_framework" != "x"; then
|
||||
AC_CHECK_FRAMEWORK(OpenAL, [#include <OpenAL/alut.h>], $with_openal_framework)
|
||||
fi
|
||||
|
||||
;;
|
||||
|
||||
*)
|
||||
@@ -346,15 +419,36 @@ AM_CONDITIONAL(EXTGL_NEEDED, test "x$ac_cv_header_windows_h" = "xyes")
|
||||
# The following are C++ items that need to be tested for with the c++
|
||||
# compiler
|
||||
|
||||
CXXCPP="g++ -E"
|
||||
AC_LANG_PUSH(C++)
|
||||
|
||||
dnl Check for "plib" without which we cannot go on
|
||||
case ${host} in
|
||||
*-apple-darwin*)
|
||||
# Check PLIB framework availability when with-plib-framework is specified
|
||||
if test "x$with_plib_framework" != "x"; then
|
||||
AC_CHECK_FRAMEWORK(PLIB, [#include <plib/ul.h>], $with_plib_framework)
|
||||
plib_FRAMEWORK="$FRAMEWORKS"
|
||||
FRAMEWORKS=""
|
||||
AC_SUBST(plib_FRAMEWORK)
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AM_CONDITIONAL(HAVE_FRAMEWORK_PLIB, test "x$ac_cv_framework_PLIB" != "x")
|
||||
|
||||
AC_CHECK_HEADER(plib/ul.h)
|
||||
if test "x$ac_cv_header_plib_ul_h" != "xyes"; then
|
||||
|
||||
AC_CHECK_LIB(plibul,ulInit)
|
||||
if test "x$ac_cv_header_plib_ul_h" != "xyes" \
|
||||
-o "x$ac_cv_lib_plibul_ulInit" != "xyes" ; then
|
||||
echo
|
||||
echo "You *must* have the plib library installed on your system to build"
|
||||
echo "SimGear!"
|
||||
echo
|
||||
echo " LIBS: '$LIBS'"
|
||||
echo " LDFLAGS: '$LDFLAGS'"
|
||||
echo " CPPFLAGS: '$CPPFLAGS'"
|
||||
echo
|
||||
echo "Please see README.plib for more details."
|
||||
echo
|
||||
echo "configure aborted."
|
||||
@@ -368,8 +462,6 @@ AC_TRY_RUN([
|
||||
#define MIN_PLIB_VERSION 185
|
||||
|
||||
int main() {
|
||||
int major, minor, micro;
|
||||
|
||||
if ( PLIB_VERSION < MIN_PLIB_VERSION ) {
|
||||
return -1;
|
||||
}
|
||||
@@ -386,16 +478,78 @@ int main() {
|
||||
|
||||
LIBS="$saved_LIBS"
|
||||
|
||||
# OpenSceneGraph
|
||||
case "${host}" in
|
||||
*-apple-darwin*)
|
||||
if test "x$with_osg_framework" != "x"; then
|
||||
# AC_CHECK_FRAMEWORK(osgViewer, [#include <osgViewer/Version>], $with_osg_framework)
|
||||
# AC_CHECK_FRAMEWORK(osgGA, [#include <osgGA/Version>], $with_osg_framework)
|
||||
# AC_CHECK_FRAMEWORK(osgText, [#include <osgText/Version>], $with_osg_framework)
|
||||
# AC_CHECK_FRAMEWORK(osgFX, [#include <osgFX/AnisotropicLighting>], $with_osg_framework)
|
||||
# AC_CHECK_FRAMEWORK(osgUtil, [#include <osgUtil/Version>], $with_osg_framework)
|
||||
# AC_CHECK_FRAMEWORK(osgDB, [#include <osgDB/Version>], $with_osg_framework)
|
||||
# AC_CHECK_FRAMEWORK(osgSim, [#include <osgSim/Version>], $with_osg_framework)
|
||||
# AC_CHECK_FRAMEWORK(osgParticle, [#include <osgParticle/Version>], $with_osg_framework)
|
||||
# AC_CHECK_FRAMEWORK(osg, [#include <osg/Version>], $with_osg_framework)
|
||||
# osg_FRAMEWORKS="$FRAMEWORKS"
|
||||
# FRAMEWORKS=""
|
||||
# AC_SUBST(osg_FRAMEWORKS)
|
||||
AC_CHECK_FRAMEWORK(OpenThreads, [#include <OpenThreads/Version>], $with_osg_framework)
|
||||
openthreads_FRAMEWORK="$FRAMEWORKS"
|
||||
FRAMEWORKS=""
|
||||
AC_SUBST(openthreads_FRAMEWORK)
|
||||
else
|
||||
dnl
|
||||
dnl This is needed when osg dynamic libs are specified
|
||||
dnl instead of OSG frameworks on Mac OS X
|
||||
dnl
|
||||
AC_CHECK_LIB(OpenThreads,OpenThreadsGetVersion)
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if test "x$enable_osgdebug" = "xyes"; then
|
||||
AC_CHECK_LIB(OpenThreadsd,OpenThreadsGetVersion)
|
||||
else
|
||||
AC_CHECK_LIB(OpenThreads,OpenThreadsGetVersion)
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
AM_CONDITIONAL(HAVE_FRAMEWORK_OSG, test "x$ac_cv_framework_osg" != "x")
|
||||
|
||||
AC_CHECK_HEADER(osg/Version)
|
||||
if test "x$ac_cv_header_osg_Version" != "xyes"; then
|
||||
|
||||
if test "x$ac_cv_header_osg_Version" != "xyes" -o "x$ac_cv_lib_OpenThreads_OpenThreadsGetVersion" != "xyes"; then
|
||||
if test "x$ac_cv_framework_osg" != "xyes"; then
|
||||
echo
|
||||
echo "You *must* have the OpenSceneGraph support library installed on your system"
|
||||
echo "You *must* have the OpenThreads library installed on your system"
|
||||
echo "to build this version of SimGear!"
|
||||
echo " Maybe you need to specify --with-osg=DIR."
|
||||
echo " Maybe you need to specify some LDFLAGS to help the linker."
|
||||
echo
|
||||
echo " LIBS: '$LIBS'"
|
||||
echo " LDFLAGS: '$LDFLAGS'"
|
||||
echo " CPPFLAGS: '$CPPFLAGS'"
|
||||
echo
|
||||
echo "Please see README.OSG for more details."
|
||||
echo
|
||||
echo "configure aborted."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADER(boost/version.hpp)
|
||||
if test "x$ac_cv_header_boost_version_hpp" != "xyes"; then
|
||||
echo
|
||||
echo "You *must* have the Boost library installed on your system"
|
||||
echo "to build this version of SimGear!"
|
||||
echo
|
||||
echo " LIBS: '$LIBS'"
|
||||
echo " LDFLAGS: '$LDFLAGS'"
|
||||
echo " CPPFLAGS: '$CPPFLAGS'"
|
||||
echo
|
||||
echo "configure aborted."
|
||||
exit
|
||||
fi
|
||||
|
||||
AC_LANG_POP
|
||||
@@ -465,6 +619,7 @@ AC_CONFIG_FILES([ \
|
||||
simgear/props/Makefile \
|
||||
simgear/route/Makefile \
|
||||
simgear/scene/Makefile \
|
||||
simgear/scene/bvh/Makefile \
|
||||
simgear/scene/material/Makefile \
|
||||
simgear/scene/model/Makefile \
|
||||
simgear/scene/sky/Makefile \
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
Debug
|
||||
Release
|
||||
SimGear.ncb
|
||||
SimGear.suo
|
||||
@@ -1,21 +0,0 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimGear", "SimGear.vcproj", "{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Debug.ActiveCfg = Debug|Win32
|
||||
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Debug.Build.0 = Debug|Win32
|
||||
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Release.ActiveCfg = Release|Win32
|
||||
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,20 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual C++ Express 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimGear", "SimGear.vcproj", "{952B5B5B-7FC8-4AE9-A664-333322BEEEB0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{952B5B5B-7FC8-4AE9-A664-333322BEEEB0}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{952B5B5B-7FC8-4AE9-A664-333322BEEEB0}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{952B5B5B-7FC8-4AE9-A664-333322BEEEB0}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{952B5B5B-7FC8-4AE9-A664-333322BEEEB0}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,5 @@
|
||||
SimGear.ncb
|
||||
SimGear.suo
|
||||
*.user
|
||||
Win32
|
||||
x64
|
||||
Executable → Regular
+2016
-1420
File diff suppressed because it is too large
Load Diff
+1
-7
@@ -1,9 +1,3 @@
|
||||
if HAVE_THREADS
|
||||
SGTHREAD_DIR = threads
|
||||
else
|
||||
SGTHREAD_DIR =
|
||||
endif
|
||||
|
||||
# METAR_DIRS =
|
||||
METAR_DIRS = environment
|
||||
|
||||
@@ -31,7 +25,7 @@ SUBDIRS = \
|
||||
screen \
|
||||
serial \
|
||||
sound \
|
||||
$(SGTHREAD_DIR) \
|
||||
threads \
|
||||
timing
|
||||
|
||||
DIST_SUBDIRS = $(SUBDIRS) compatibility
|
||||
|
||||
@@ -106,7 +106,7 @@ void SGBucket::set_bucket( double dlon, double dlat ) {
|
||||
} else if ( span <= 1.0 ) {
|
||||
x = (int)((dlon - lon) / span);
|
||||
} else {
|
||||
if ( (dlon >= 0) || (fabs(diff) < SG_EPSILON) ) {
|
||||
if ( dlon >= 0 ) {
|
||||
lon = (int)( (int)(lon / span) * span);
|
||||
} else {
|
||||
// cout << " lon = " << lon
|
||||
|
||||
@@ -95,7 +95,6 @@ static double sg_bucket_span( double l ) {
|
||||
class SGBucket {
|
||||
|
||||
private:
|
||||
double cx, cy; // centerpoint (lon, lat) in degrees of bucket
|
||||
short lon; // longitude index (-180 to 179)
|
||||
short lat; // latitude index (-90 to 89)
|
||||
char x; // x subdivision (0 to 7)
|
||||
|
||||
+26
-1
@@ -63,6 +63,9 @@
|
||||
# if _MSC_VER >= 1200 // msvc++ 6.0 or greater
|
||||
# define isnan _isnan
|
||||
# define snprintf _snprintf
|
||||
# if _MSC_VER < 1500
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# define copysign _copysign
|
||||
|
||||
# pragma warning(disable: 4786) // identifier was truncated to '255' characters
|
||||
@@ -131,9 +134,31 @@
|
||||
//
|
||||
|
||||
#ifdef __APPLE__
|
||||
# ifdef __GNUC__
|
||||
# if ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 3 )
|
||||
inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
|
||||
#else
|
||||
# else
|
||||
// any C++ header file undefines isinf and isnan
|
||||
// so this should be included before <iostream>
|
||||
// the functions are STILL in libm (libSystem on mac os x)
|
||||
extern "C" int (isnan)(double);
|
||||
extern "C" int (isinf)(double);
|
||||
# endif
|
||||
# else
|
||||
inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__FreeBSD__)
|
||||
# if __FreeBSD_version < 500000
|
||||
extern "C" {
|
||||
inline int isnan(double r) { return !(r <= 0 || r >= 0); }
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__CYGWIN__)
|
||||
# include <ieeefp.h> // isnan
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+5
-5
@@ -118,10 +118,10 @@
|
||||
/** Nautical Miles to Radians */
|
||||
#define SG_RAD_TO_NM 3437.7467707849392526
|
||||
|
||||
/** Miles per second to Knots */
|
||||
/** meters per second to Knots */
|
||||
#define SG_MPS_TO_KT 1.9438444924406046432
|
||||
|
||||
/** Knots to Miles per second */
|
||||
/** Knots to meters per second */
|
||||
#define SG_KT_TO_MPS 0.5144444444444444444
|
||||
|
||||
/** Feet per second to Knots */
|
||||
@@ -130,16 +130,16 @@
|
||||
/** Knots to Feet per second */
|
||||
#define SG_KT_TO_FPS 1.6878098571011956874
|
||||
|
||||
/** Miles per second to Miles per hour */
|
||||
/** meters per second to Miles per hour */
|
||||
#define SG_MPS_TO_MPH 2.2369362920544020312
|
||||
|
||||
/** Miles per hour to Miles per second */
|
||||
/** meetrs per hour to Miles per second */
|
||||
#define SG_MPH_TO_MPS 0.44704
|
||||
|
||||
/** Meters per second to Kilometers per hour */
|
||||
#define SG_MPS_TO_KMH 3.6
|
||||
|
||||
/** Kilometers per hour to Miles per second */
|
||||
/** Kilometers per hour to meters per second */
|
||||
#define SG_KMH_TO_MPS 0.2777777777777777778
|
||||
|
||||
/** Pascal to Inch Mercury */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
logstream *logstream::global_logstream = 0;
|
||||
|
||||
bool logbuf::logging_enabled = true;
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _WIN32
|
||||
bool logbuf::has_console = true;
|
||||
#endif
|
||||
sgDebugClass logbuf::logClass = SG_NONE;
|
||||
|
||||
@@ -27,12 +27,13 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <streambuf>
|
||||
#include <ostream>
|
||||
#include <cstdio>
|
||||
|
||||
#include <simgear/debug/debug_types.h>
|
||||
|
||||
@@ -122,7 +123,7 @@ public:
|
||||
*/
|
||||
void set_sb( std::streambuf* sb );
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _WIN32
|
||||
static void has_no_console() { has_console = false; }
|
||||
#endif
|
||||
|
||||
@@ -141,7 +142,7 @@ private:
|
||||
static std::streambuf* sbuf;
|
||||
|
||||
static bool logging_enabled;
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _WIN32
|
||||
static bool has_console;
|
||||
#endif
|
||||
static sgDebugClass logClass;
|
||||
@@ -175,7 +176,7 @@ logbuf::would_log( sgDebugClass c, sgDebugPriority p ) const
|
||||
inline logbuf::int_type
|
||||
logbuf::overflow( int c )
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _WIN32
|
||||
if ( logging_enabled ) {
|
||||
if ( !has_console ) {
|
||||
AllocConsole();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <string>
|
||||
#include "Debug/logstream.hxx"
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
class Test {
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ void SGMetar::useCurrentDate()
|
||||
{
|
||||
struct tm now;
|
||||
time_t now_sec = time(0);
|
||||
#if defined( _MSC_VER ) || defined ( __MINGW32__ )
|
||||
#ifdef _WIN32
|
||||
now = *gmtime(&now_sec);
|
||||
#else
|
||||
gmtime_r(&now_sec, &now);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "visual_enviro.hxx"
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <osg/ClipNode>
|
||||
|
||||
/**
|
||||
* @brief SGPrecipitation constructor
|
||||
@@ -35,7 +36,7 @@
|
||||
* Build a new OSG object from osgParticle.
|
||||
*/
|
||||
SGPrecipitation::SGPrecipitation() :
|
||||
_freeze(false), _snow_intensity(0.0), _rain_intensity(0.0)
|
||||
_freeze(false), _snow_intensity(0.0), _rain_intensity(0.0), _clip_distance(5.0)
|
||||
{
|
||||
_precipitationEffect = new osgParticle::PrecipitationEffect;
|
||||
}
|
||||
@@ -54,7 +55,20 @@ osg::Group* SGPrecipitation::build(void)
|
||||
_precipitationEffect->snow(0);
|
||||
_precipitationEffect->rain(0);
|
||||
|
||||
group->addChild(_precipitationEffect.get());
|
||||
if (_clip_distance!=0.0)
|
||||
{
|
||||
osg::ref_ptr<osg::ClipNode> clipNode = new osg::ClipNode;
|
||||
clipNode->addClipPlane( new osg::ClipPlane( 0 ) );
|
||||
clipNode->getClipPlane(0)->setClipPlane( 0.0, 0.0, -1.0, -_clip_distance );
|
||||
clipNode->setReferenceFrame(osg::ClipNode::ABSOLUTE_RF);
|
||||
clipNode->addChild(_precipitationEffect.get());
|
||||
|
||||
group->addChild(clipNode.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
group->addChild(_precipitationEffect.get());
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ private:
|
||||
|
||||
float _snow_intensity;
|
||||
float _rain_intensity;
|
||||
float _clip_distance;
|
||||
|
||||
int _wind_dir;
|
||||
osg::Vec3 _wind_vec;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/math/polar3d.hxx>
|
||||
#include <simgear/sound/soundmgr_openal.hxx>
|
||||
#include <simgear/sound/sample_group.hxx>
|
||||
#include <simgear/scene/sky/cloudfield.hxx>
|
||||
#include <simgear/scene/sky/newcloud.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
@@ -175,7 +175,7 @@ SGEnviro::SGEnviro() :
|
||||
lightning_enable_state(false),
|
||||
elapsed_time(0.0),
|
||||
dt(0.0),
|
||||
soundMgr(NULL),
|
||||
sampleGroup(NULL),
|
||||
snd_active(false),
|
||||
snd_dist(0.0),
|
||||
min_time_before_lt(0.0),
|
||||
@@ -189,6 +189,8 @@ SGEnviro::SGEnviro() :
|
||||
}
|
||||
|
||||
SGEnviro::~SGEnviro(void) {
|
||||
if (sampleGroup) delete sampleGroup;
|
||||
|
||||
// OSGFIXME
|
||||
return;
|
||||
list_of_lightning::iterator iLightning;
|
||||
@@ -530,8 +532,8 @@ void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed
|
||||
|
||||
}
|
||||
|
||||
void SGEnviro::set_soundMgr(SGSoundMgr *mgr) {
|
||||
soundMgr = mgr;
|
||||
void SGEnviro::set_sampleGroup(SGSampleGroup *sgr) {
|
||||
sampleGroup = sgr;
|
||||
}
|
||||
|
||||
void SGEnviro::drawPrecipitation(double rain_norm, double snow_norm, double hail_norm, double pitch, double roll, double heading, double hspeed) {
|
||||
@@ -616,7 +618,7 @@ void SGLightning::lt_build(void) {
|
||||
top[PY] = alt;
|
||||
top[PZ] = 0;
|
||||
lt_build_tree_branch(0, top, 1.0, 50, top[PY] / 8.0);
|
||||
if( ! sgEnviro.soundMgr )
|
||||
if( ! sgEnviro.sampleGroup )
|
||||
return;
|
||||
Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 );
|
||||
Point3D dest( lon*SG_DEGREES_TO_RADIANS, lat*SG_DEGREES_TO_RADIANS, 0.0 );
|
||||
@@ -737,7 +739,7 @@ void SGEnviro::drawLightning(void) {
|
||||
return;
|
||||
list_of_lightning::iterator iLightning;
|
||||
// play 'thunder' for lightning
|
||||
if( snd_active )
|
||||
if( snd_active ) {
|
||||
if( !snd_playing ) {
|
||||
// wait until sound has reached us
|
||||
snd_timer += dt;
|
||||
@@ -751,20 +753,21 @@ void SGEnviro::drawLightning(void) {
|
||||
double ax = 0.0, ay = 0.0;
|
||||
ax = cos(course) * dist;
|
||||
ay = sin(course) * dist;
|
||||
SGSharedPtr<SGSoundSample> snd = soundMgr->find("thunder");
|
||||
SGSharedPtr<SGSoundSample> snd = sampleGroup->find("thunder");
|
||||
if( snd ) {
|
||||
ALfloat pos[3]={ax, ay, -sgEnviro.last_alt };
|
||||
snd->set_source_pos(pos);
|
||||
SGVec3d pos = SGVec3d(ax, ay, -sgEnviro.last_alt);
|
||||
snd->set_position(pos);
|
||||
snd->play_once();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if( !soundMgr->is_playing("thunder") ) {
|
||||
if( !sampleGroup->is_playing("thunder") ) {
|
||||
snd_active = false;
|
||||
snd_playing = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if( ! lightning_enable_state )
|
||||
return;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ using std::vector;
|
||||
using std::string;
|
||||
|
||||
class SGLightning;
|
||||
class SGSoundMgr;
|
||||
class SGSampleGroup;
|
||||
|
||||
/**
|
||||
* Simulate some echo on a weather radar.
|
||||
@@ -84,7 +84,7 @@ private:
|
||||
sgVec4 fog_color;
|
||||
sgMat4 transform;
|
||||
double last_lon, last_lat, last_alt;
|
||||
SGSoundMgr *soundMgr;
|
||||
SGSampleGroup *sampleGroup;
|
||||
bool snd_active, snd_playing;
|
||||
double snd_timer, snd_wait, snd_pos_lat, snd_pos_lon, snd_dist;
|
||||
double min_time_before_lt;
|
||||
@@ -243,7 +243,7 @@ public:
|
||||
* Forward the sound manager instance to be able to play samples.
|
||||
* @param mgr a running sound manager
|
||||
*/
|
||||
void set_soundMgr(SGSoundMgr *mgr);
|
||||
void set_sampleGroup(SGSampleGroup *sgr);
|
||||
|
||||
void setFOV( float w, float h );
|
||||
void getFOV( float &w, float &h );
|
||||
|
||||
@@ -158,6 +158,7 @@ public:
|
||||
* @return planets array
|
||||
*/
|
||||
inline SGVec3d *getPlanets() { return planets; }
|
||||
inline const SGVec3d *getPlanets() const { return planets; }
|
||||
|
||||
/** @return the numbers of defined stars. */
|
||||
inline int getNumStars() const { return stars->getNumStars(); }
|
||||
@@ -170,6 +171,7 @@ public:
|
||||
* @returns star array
|
||||
*/
|
||||
inline SGVec3d *getStars() { return stars->getStars(); }
|
||||
inline const SGVec3d *getStars() const { return stars->getStars(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
+22
-4
@@ -26,36 +26,54 @@ noinst_PROGRAMS = decode_binobj socktest lowtest tcp_server tcp_client
|
||||
|
||||
tcp_server_SOURCES = tcp_server.cxx
|
||||
|
||||
if HAVE_FRAMEWORK_PLIB
|
||||
tcp_server_LDFLAGS = $(plib_FRAMEWORK)
|
||||
else
|
||||
tcp_server_PLIB_LIBS = -lplibnet -lplibul
|
||||
endif
|
||||
|
||||
tcp_server_LDADD = \
|
||||
libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||
-lplibnet -lplibul -lz \
|
||||
$(tcp_server_PLIB_LIBS) -lz \
|
||||
$(network_LIBS) \
|
||||
$(base_LIBS)
|
||||
|
||||
tcp_client_SOURCES = tcp_client.cxx
|
||||
|
||||
if HAVE_FRAMEWORK_PLIB
|
||||
tcp_client_LDFLAGS = $(plib_FRAMEWORK)
|
||||
else
|
||||
tcp_client_PLIB_LIBS = -lplibnet -lplibul
|
||||
endif
|
||||
|
||||
tcp_client_LDADD = \
|
||||
libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||
-lplibnet -lplibul -lz \
|
||||
$(tcp_client_PLIB_LIBS) -lz \
|
||||
$(network_LIBS) \
|
||||
$(base_LIBS)
|
||||
|
||||
socktest_SOURCES = socktest.cxx
|
||||
|
||||
if HAVE_FRAMEWORK_PLIB
|
||||
socktest_LDFLAGS = $(plib_FRAMEWORK)
|
||||
else
|
||||
socktest_PLIB_LIBS = -lplibnet -lplibul
|
||||
endif
|
||||
|
||||
socktest_LDADD = \
|
||||
libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||
-lplibnet -lplibul -lz \
|
||||
$(socktest_PLIB_LIBS) -lz \
|
||||
$(network_LIBS) \
|
||||
$(base_LIBS)
|
||||
$(base_LIBS)
|
||||
|
||||
lowtest_SOURCES = lowtest.cxx
|
||||
|
||||
|
||||
+16
-8
@@ -55,21 +55,25 @@ void sgWriteChar ( gzFile fd, const char var )
|
||||
|
||||
void sgReadFloat ( gzFile fd, float *var )
|
||||
{
|
||||
if ( gzread ( fd, var, sizeof(float) ) != sizeof(float) ) {
|
||||
union { float v; uint32_t u; } buf;
|
||||
if ( gzread ( fd, &buf.u, sizeof(float) ) != sizeof(float) ) {
|
||||
read_error = true ;
|
||||
}
|
||||
if ( sgIsBigEndian() ) {
|
||||
sgEndianSwap( (uint32_t *)var);
|
||||
sgEndianSwap( &buf.u );
|
||||
}
|
||||
*var = buf.v;
|
||||
}
|
||||
|
||||
|
||||
void sgWriteFloat ( gzFile fd, const float var )
|
||||
{
|
||||
union { float v; uint32_t u; } buf;
|
||||
buf.v = var;
|
||||
if ( sgIsBigEndian() ) {
|
||||
sgEndianSwap( (uint32_t *)&var);
|
||||
sgEndianSwap( &buf.u );
|
||||
}
|
||||
if ( gzwrite ( fd, (void *)(&var), sizeof(float) ) != sizeof(float) ) {
|
||||
if ( gzwrite ( fd, (void *)(&buf.u), sizeof(float) ) != sizeof(float) ) {
|
||||
write_error = true ;
|
||||
}
|
||||
}
|
||||
@@ -77,21 +81,25 @@ void sgWriteFloat ( gzFile fd, const float var )
|
||||
|
||||
void sgReadDouble ( gzFile fd, double *var )
|
||||
{
|
||||
if ( gzread ( fd, var, sizeof(double) ) != sizeof(double) ) {
|
||||
union { double v; uint64_t u; } buf;
|
||||
if ( gzread ( fd, &buf.u, sizeof(double) ) != sizeof(double) ) {
|
||||
read_error = true ;
|
||||
}
|
||||
if ( sgIsBigEndian() ) {
|
||||
sgEndianSwap( (uint64_t *)var);
|
||||
sgEndianSwap( &buf.u );
|
||||
}
|
||||
*var = buf.v;
|
||||
}
|
||||
|
||||
|
||||
void sgWriteDouble ( gzFile fd, const double var )
|
||||
{
|
||||
union { double v; uint64_t u; } buf;
|
||||
buf.v = var;
|
||||
if ( sgIsBigEndian() ) {
|
||||
sgEndianSwap( (uint64_t *)&var);
|
||||
sgEndianSwap( &buf.u );
|
||||
}
|
||||
if ( gzwrite ( fd, (void *)(&var), sizeof(double) ) != sizeof(double) ) {
|
||||
if ( gzwrite ( fd, (void *)(&buf.u), sizeof(double) ) != sizeof(double) ) {
|
||||
write_error = true ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/bucket/newbucket.hxx>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
@@ -55,7 +55,7 @@ bool SGFile::open( const SGProtocolDir d ) {
|
||||
set_dir( d );
|
||||
|
||||
if ( get_dir() == SG_IO_OUT ) {
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#ifdef _WIN32
|
||||
int mode = 00666;
|
||||
#else
|
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define sleep(x) Sleep(x*1000)
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
|
||||
#include "sg_socket.hxx"
|
||||
@@ -44,10 +49,6 @@ int main() {
|
||||
if ( s.readline( buf, 256 ) > 0 ) {
|
||||
cout << "result = " << buf;
|
||||
}
|
||||
#ifdef __MINGW32__
|
||||
Sleep(100);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ class TcpServer
|
||||
{
|
||||
public:
|
||||
TcpServer();
|
||||
~TcpServer();
|
||||
bool open();
|
||||
bool process();
|
||||
bool close();
|
||||
@@ -25,6 +26,11 @@ TcpServer::TcpServer()
|
||||
channel = new SGSocket( "", "5500", "tcp" );
|
||||
}
|
||||
|
||||
TcpServer::~TcpServer()
|
||||
{
|
||||
delete channel;
|
||||
}
|
||||
|
||||
bool
|
||||
TcpServer::open()
|
||||
{
|
||||
|
||||
@@ -2,11 +2,9 @@ includedir = @includedir@/magvar
|
||||
|
||||
lib_LIBRARIES = libsgmagvar.a
|
||||
|
||||
include_HEADERS = magvar.hxx
|
||||
include_HEADERS = magvar.hxx coremag.hxx
|
||||
|
||||
libsgmagvar_a_SOURCES = \
|
||||
coremag.hxx coremag.cxx \
|
||||
magvar.cxx
|
||||
libsgmagvar_a_SOURCES = coremag.cxx magvar.cxx
|
||||
|
||||
noinst_PROGRAMS = testmagvar
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <simgear/magvar/magvar.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
#include "coremag.hxx"
|
||||
#include "magvar.hxx"
|
||||
@@ -47,6 +48,12 @@ void SGMagVar::update( double lon, double lat, double alt_m, double jd ) {
|
||||
magdip = atan(field[5]/sqrt(field[3]*field[3]+field[4]*field[4]));
|
||||
}
|
||||
|
||||
void SGMagVar::update( const SGGeod& geod, double jd ) {
|
||||
|
||||
update(geod.getLongitudeDeg(), geod.getLatitudeDeg(),
|
||||
geod.getElevationM(), jd);
|
||||
}
|
||||
|
||||
|
||||
double sgGetMagVar( double lon, double lat, double alt_m, double jd ) {
|
||||
// cout << "lat = " << lat << " lon = " << lon << " elev = " << alt_m
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
// forward decls
|
||||
class SGGeod;
|
||||
|
||||
/**
|
||||
* Magnetic variation wrapper class.
|
||||
*
|
||||
@@ -78,6 +81,11 @@ public:
|
||||
*/
|
||||
void update( double lon, double lat, double alt_m, double jd );
|
||||
|
||||
/**
|
||||
* overloaded variant taking an SGGeod to specify position
|
||||
*/
|
||||
void update( const SGGeod& geod, double jd );
|
||||
|
||||
/** @return the current magnetic variation in radians. */
|
||||
double get_magvar() const { return magvar; }
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ check_PROGRAMS = SGMathTest SGGeometryTest
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
SGMathTest_SOURCES = SGMathTest.cxx
|
||||
SGMathTest_LDADD = libsgmath.a $(base_LIBS)
|
||||
SGMathTest_LDADD = libsgmath.a -lsgstructure $(base_LIBS)
|
||||
|
||||
SGGeometryTest_SOURCES = SGGeometryTest.cxx
|
||||
SGGeometryTest_LDADD = libsgmath.a $(base_LIBS)
|
||||
SGGeometryTest_LDADD = libsgmath.a -lsgstructure $(base_LIBS)
|
||||
|
||||
lib_LIBRARIES = libsgmath.a
|
||||
|
||||
@@ -42,7 +42,8 @@ include_HEADERS = \
|
||||
SGTriangle.hxx \
|
||||
SGVec2.hxx \
|
||||
SGVec3.hxx \
|
||||
SGVec4.hxx
|
||||
SGVec4.hxx \
|
||||
beziercurve.hxx
|
||||
|
||||
libsgmath_a_SOURCES = \
|
||||
interpolater.cxx \
|
||||
|
||||
+60
-1
@@ -25,6 +25,20 @@ public:
|
||||
_min(SGLimits<T>::max(), SGLimits<T>::max(), SGLimits<T>::max()),
|
||||
_max(-SGLimits<T>::max(), -SGLimits<T>::max(), -SGLimits<T>::max())
|
||||
{ }
|
||||
SGBox(const SGVec3<T>& pt) :
|
||||
_min(pt),
|
||||
_max(pt)
|
||||
{ }
|
||||
SGBox(const SGVec3<T>& min, const SGVec3<T>& max) :
|
||||
_min(min),
|
||||
_max(max)
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGBox(const SGBox<S>& box) :
|
||||
_min(box.getMin()),
|
||||
_max(box.getMax())
|
||||
{ }
|
||||
|
||||
void setMin(const SGVec3<T>& min)
|
||||
{ _min = min; }
|
||||
const SGVec3<T>& getMin() const
|
||||
@@ -35,6 +49,37 @@ public:
|
||||
const SGVec3<T>& getMax() const
|
||||
{ return _max; }
|
||||
|
||||
SGVec3<T> getCorner(unsigned i) const
|
||||
{ return SGVec3<T>((i&1) ? _min[0] : _max[0],
|
||||
(i&2) ? _min[1] : _max[1],
|
||||
(i&4) ? _min[2] : _max[2]); }
|
||||
|
||||
template<typename S>
|
||||
SGVec3<T> getNearestCorner(const SGVec3<S>& pt) const
|
||||
{
|
||||
SGVec3<T> center = getCenter();
|
||||
return SGVec3<T>((pt[0] <= center[0]) ? _min[0] : _max[0],
|
||||
(pt[1] <= center[1]) ? _min[1] : _max[1],
|
||||
(pt[2] <= center[2]) ? _min[2] : _max[2]);
|
||||
}
|
||||
template<typename S>
|
||||
SGVec3<T> getFarestCorner(const SGVec3<S>& pt) const
|
||||
{
|
||||
SGVec3<T> center = getCenter();
|
||||
return SGVec3<T>((pt[0] > center[0]) ? _min[0] : _max[0],
|
||||
(pt[1] > center[1]) ? _min[1] : _max[1],
|
||||
(pt[2] > center[2]) ? _min[2] : _max[2]);
|
||||
}
|
||||
|
||||
// return the closest point to pt still in the box
|
||||
template<typename S>
|
||||
SGVec3<T> getClosestPoint(const SGVec3<S>& pt) const
|
||||
{
|
||||
return SGVec3<T>((pt[0] < _min[0]) ? _min[0] : ((_max[0] < pt[0]) ? _max[0] : T(pt[0])),
|
||||
(pt[1] < _min[1]) ? _min[1] : ((_max[1] < pt[1]) ? _max[1] : T(pt[1])),
|
||||
(pt[2] < _min[2]) ? _min[2] : ((_max[2] < pt[2]) ? _max[2] : T(pt[2])));
|
||||
}
|
||||
|
||||
// Only works for floating point types
|
||||
SGVec3<T> getCenter() const
|
||||
{ return T(0.5)*(_min + _max); }
|
||||
@@ -42,6 +87,8 @@ public:
|
||||
// Only valid for nonempty boxes
|
||||
SGVec3<T> getSize() const
|
||||
{ return _max - _min; }
|
||||
SGVec3<T> getHalfSize() const
|
||||
{ return T(0.5)*getSize(); }
|
||||
|
||||
T getVolume() const
|
||||
{
|
||||
@@ -83,7 +130,7 @@ public:
|
||||
// Note that this only works if the box is nonmepty
|
||||
unsigned getBroadestAxis() const
|
||||
{
|
||||
SGVec3d size = getSize();
|
||||
SGVec3<T> size = getSize();
|
||||
if (size[1] <= size[0] && size[2] <= size[0])
|
||||
return 0;
|
||||
else if (size[2] <= size[1])
|
||||
@@ -92,6 +139,18 @@ public:
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Note that this only works if the box is nonmepty
|
||||
unsigned getSmallestAxis() const
|
||||
{
|
||||
SGVec3<T> size = getSize();
|
||||
if (size[1] >= size[0] && size[2] >= size[0])
|
||||
return 0;
|
||||
else if (size[2] >= size[1])
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
private:
|
||||
SGVec3<T> _min;
|
||||
SGVec3<T> _max;
|
||||
|
||||
@@ -79,6 +79,8 @@ public:
|
||||
static double courseDeg(const SGGeoc& from, const SGGeoc& to);
|
||||
static double distanceM(const SGGeoc& from, const SGGeoc& to);
|
||||
|
||||
// Compare two geocentric positions for equality
|
||||
bool operator == ( const SGGeoc & other ) const;
|
||||
private:
|
||||
/// This one is private since construction is not unique if you do
|
||||
/// not know the units of the arguments, use the factory methods for
|
||||
@@ -323,6 +325,15 @@ SGGeoc::distanceM(const SGGeoc& from, const SGGeoc& to)
|
||||
return SGGeodesy::distanceM(from, to);
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
SGGeoc::operator == ( const SGGeoc & other ) const
|
||||
{
|
||||
return _lon == other._lon &&
|
||||
_lat == other._lat &&
|
||||
_radius == other._radius;
|
||||
}
|
||||
|
||||
/// Output to an ostream
|
||||
template<typename char_type, typename traits_type>
|
||||
inline
|
||||
|
||||
+11
-7
@@ -17,22 +17,24 @@
|
||||
|
||||
#include "SGMath.hxx"
|
||||
|
||||
osg::Matrix SGGeod::makeSimulationFrameRelative()
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
|
||||
osg::Matrix SGGeod::makeSimulationFrameRelative() const
|
||||
{
|
||||
SGQuatd hlOr = SGQuatd::fromLonLat(*this);
|
||||
return osg::Matrix(hlOr.osg());
|
||||
return osg::Matrix(toOsg(hlOr));
|
||||
}
|
||||
|
||||
osg::Matrix SGGeod::makeSimulationFrame()
|
||||
osg::Matrix SGGeod::makeSimulationFrame() const
|
||||
{
|
||||
osg::Matrix result(makeSimulationFrameRelative());
|
||||
SGVec3d coord;
|
||||
SGGeodesy::SGGeodToCart(*this, coord);
|
||||
result.setTrans(coord.osg());
|
||||
result.setTrans(toOsg(coord));
|
||||
return result;
|
||||
}
|
||||
|
||||
osg::Matrix SGGeod::makeZUpFrameRelative()
|
||||
osg::Matrix SGGeod::makeZUpFrameRelative() const
|
||||
{
|
||||
osg::Matrix result(makeSimulationFrameRelative());
|
||||
// 180 degree rotation around Y axis
|
||||
@@ -41,11 +43,13 @@ osg::Matrix SGGeod::makeZUpFrameRelative()
|
||||
return result;
|
||||
}
|
||||
|
||||
osg::Matrix SGGeod::makeZUpFrame()
|
||||
osg::Matrix SGGeod::makeZUpFrame() const
|
||||
{
|
||||
osg::Matrix result(makeZUpFrameRelative());
|
||||
SGVec3d coord;
|
||||
SGGeodesy::SGGeodToCart(*this, coord);
|
||||
result.setTrans(coord.osg());
|
||||
result.setTrans(toOsg(coord));
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+40
-6
@@ -20,7 +20,9 @@
|
||||
|
||||
#include <simgear/constants.h>
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Matrix>
|
||||
#endif
|
||||
|
||||
// #define SG_GEOD_NATIVE_DEGREE
|
||||
|
||||
@@ -42,6 +44,10 @@ public:
|
||||
static SGGeod fromRadM(double lon, double lat, double elevation);
|
||||
/// Factory from angular values in degrees and elevation in m
|
||||
static SGGeod fromDegM(double lon, double lat, double elevation);
|
||||
/// Factory from an other SGGeod and a different elevation in m
|
||||
static SGGeod fromGeodM(const SGGeod& geod, double elevation);
|
||||
/// Factory from an other SGGeod and a different elevation in ft
|
||||
static SGGeod fromGeodFt(const SGGeod& geod, double elevation);
|
||||
/// Factory to convert position from a cartesian position assumed to be
|
||||
/// in wgs84 measured in meters
|
||||
/// Note that this conversion is relatively expensive to compute
|
||||
@@ -80,25 +86,30 @@ public:
|
||||
/// Set the geodetic elevation from the argument given in feet
|
||||
void setElevationFt(double elevation);
|
||||
|
||||
// Compare two geodetic positions for equality
|
||||
bool operator == ( const SGGeod & other ) const;
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
// Create a local coordinate frame in the earth-centered frame of
|
||||
// reference. X points north, Z points down.
|
||||
// makeSimulationFrameRelative() only includes rotation.
|
||||
|
||||
osg::Matrix makeSimulationFrameRelative();
|
||||
osg::Matrix makeSimulationFrame();
|
||||
osg::Matrix makeSimulationFrameRelative() const;
|
||||
osg::Matrix makeSimulationFrame() const;
|
||||
|
||||
// Create a Z-up local coordinate frame in the earth-centered frame
|
||||
// of reference. This is what scenery models, etc. expect.
|
||||
// makeZUpFrameRelative() only includes rotation.
|
||||
osg::Matrix makeZUpFrameRelative();
|
||||
osg::Matrix makeZUpFrame();
|
||||
osg::Matrix makeZUpFrameRelative() const;
|
||||
osg::Matrix makeZUpFrame() const;
|
||||
#endif
|
||||
private:
|
||||
/// This one is private since construction is not unique if you do
|
||||
/// not know the units of the arguments. Use the factory methods for
|
||||
/// that purpose
|
||||
SGGeod(double lon, double lat, double elevation);
|
||||
|
||||
/// The actual data, angles in degree, elevation in meters
|
||||
//// FIXME: wrong comment!
|
||||
/// The actual data, angles in degrees, elevation in meters
|
||||
/// The rationale for storing the values in degrees is that most code places
|
||||
/// in flightgear/terragear use degrees as a nativ input and output value.
|
||||
/// The places where it makes sense to use radians is when we convert
|
||||
@@ -192,6 +203,20 @@ SGGeod::fromDegM(double lon, double lat, double elevation)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
SGGeod
|
||||
SGGeod::fromGeodM(const SGGeod& geod, double elevation)
|
||||
{
|
||||
return SGGeod(geod._lon, geod._lat, elevation);
|
||||
}
|
||||
|
||||
inline
|
||||
SGGeod
|
||||
SGGeod::fromGeodFt(const SGGeod& geod, double elevation)
|
||||
{
|
||||
return SGGeod(geod._lon, geod._lat, elevation*SG_FEET_TO_METER);
|
||||
}
|
||||
|
||||
inline
|
||||
SGGeod
|
||||
SGGeod::fromCart(const SGVec3<double>& cart)
|
||||
@@ -328,6 +353,15 @@ SGGeod::setElevationFt(double elevation)
|
||||
_elevation = elevation*SG_FEET_TO_METER;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
SGGeod::operator == ( const SGGeod & other ) const
|
||||
{
|
||||
return _lon == other._lon &&
|
||||
_lat == other._lat &&
|
||||
_elevation == other._elevation;
|
||||
}
|
||||
|
||||
/// Output to an ostream
|
||||
template<typename char_type, typename traits_type>
|
||||
inline
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include "SGMath.hxx"
|
||||
|
||||
// These are hard numbers from the WGS84 standard. DON'T MODIFY
|
||||
@@ -56,7 +57,7 @@ const double SGGeodesy::POLRAD = _POLRAD;
|
||||
#define E2 fabs(1 - _SQUASH*_SQUASH)
|
||||
static double a = _EQURAD;
|
||||
static double ra2 = 1/(_EQURAD*_EQURAD);
|
||||
static double e = sqrt(E2);
|
||||
//static double e = sqrt(E2);
|
||||
static double e2 = E2;
|
||||
static double e4 = E2*E2;
|
||||
|
||||
@@ -78,11 +79,30 @@ SGGeodesy::SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod)
|
||||
double Y = cart(1);
|
||||
double Z = cart(2);
|
||||
double XXpYY = X*X+Y*Y;
|
||||
if( XXpYY + Z*Z < 25 ) {
|
||||
// This function fails near the geocenter region, so catch that special case here.
|
||||
// Define the innermost sphere of small radius as earth center and return the
|
||||
// coordinates 0/0/-EQURAD. It may be any other place on geoide's surface,
|
||||
// the Northpole, Hawaii or Wentorf. This one was easy to code ;-)
|
||||
geod.setLongitudeRad( 0.0 );
|
||||
geod.setLongitudeRad( 0.0 );
|
||||
geod.setElevationM( -EQURAD );
|
||||
return;
|
||||
}
|
||||
|
||||
double sqrtXXpYY = sqrt(XXpYY);
|
||||
double p = XXpYY*ra2;
|
||||
double q = Z*Z*(1-e2)*ra2;
|
||||
double r = 1/6.0*(p+q-e4);
|
||||
double s = e4*p*q/(4*r*r*r);
|
||||
/*
|
||||
s*(2+s) is negative for s = [-2..0]
|
||||
slightly negative values for s due to floating point rounding errors
|
||||
cause nan for sqrt(s*(2+s))
|
||||
We can probably clamp the resulting parable to positive numbers
|
||||
*/
|
||||
if( s >= -2.0 && s <= 0.0 )
|
||||
s = 0.0;
|
||||
double t = pow(1+s+sqrt(s*(2+s)), 1/3.0);
|
||||
double u = r*(1+t+1/t);
|
||||
double v = sqrt(u*u+e4*q);
|
||||
@@ -314,7 +334,7 @@ static int _geo_inverse_wgs_84( double lat1, double lon1, double lat2,
|
||||
double sinphi2 = sin(phi2), cosphi2 = cos(phi2);
|
||||
|
||||
if( (fabs(lat1-lat2) < testv &&
|
||||
( fabs(lon1-lon2) < testv) || fabs(lat1-90.0) < testv ) )
|
||||
( fabs(lon1-lon2) < testv)) || (fabs(lat1-90.0) < testv ) )
|
||||
{
|
||||
// TWO STATIONS ARE IDENTICAL : SET DISTANCE & AZIMUTHS TO ZERO */
|
||||
*az1 = 0.0; *az2 = 0.0; *s = 0.0;
|
||||
@@ -423,6 +443,40 @@ SGGeodesy::inverse(const SGGeod& p1, const SGGeod& p2, double& course1,
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
double
|
||||
SGGeodesy::courseDeg(const SGGeod& p1, const SGGeod& p2)
|
||||
{
|
||||
double course1, course2, distance;
|
||||
int r = _geo_inverse_wgs_84(p1.getLatitudeDeg(), p1.getLongitudeDeg(),
|
||||
p2.getLatitudeDeg(), p2.getLongitudeDeg(),
|
||||
&course1, &course2, &distance);
|
||||
if (r != 0) {
|
||||
throw sg_exception("SGGeodesy::courseDeg, unable to compute course");
|
||||
}
|
||||
|
||||
return course1;
|
||||
}
|
||||
|
||||
double
|
||||
SGGeodesy::distanceM(const SGGeod& p1, const SGGeod& p2)
|
||||
{
|
||||
double course1, course2, distance;
|
||||
int r = _geo_inverse_wgs_84(p1.getLatitudeDeg(), p1.getLongitudeDeg(),
|
||||
p2.getLatitudeDeg(), p2.getLongitudeDeg(),
|
||||
&course1, &course2, &distance);
|
||||
if (r != 0) {
|
||||
throw sg_exception("SGGeodesy::distanceM, unable to compute distance");
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
double
|
||||
SGGeodesy::distanceNm(const SGGeod& from, const SGGeod& to)
|
||||
{
|
||||
return distanceM(from, to) * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
/// Geocentric routines
|
||||
|
||||
void
|
||||
@@ -486,7 +540,7 @@ SGGeodesy::courseRad(const SGGeoc& from, const SGGeoc& to)
|
||||
}
|
||||
|
||||
double
|
||||
SGGeodesy::distanceM(const SGGeoc& from, const SGGeoc& to)
|
||||
SGGeodesy::distanceRad(const SGGeoc& from, const SGGeoc& to)
|
||||
{
|
||||
// d = 2*asin(sqrt((sin((lat1-lat2)/2))^2 +
|
||||
// cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2))
|
||||
@@ -496,5 +550,12 @@ SGGeodesy::distanceM(const SGGeoc& from, const SGGeoc& to)
|
||||
double tmp2 = sin(0.5*(from.getLongitudeRad() - to.getLongitudeRad()));
|
||||
double square = tmp1*tmp1 + cosLatFrom*cosLatTo*tmp2*tmp2;
|
||||
double s = SGMiscd::min(sqrt(SGMiscd::max(square, 0)), 1);
|
||||
return 2 * asin(s) * SG_RAD_TO_NM * SG_NM_TO_METER;
|
||||
return 2 * asin(s);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
SGGeodesy::distanceM(const SGGeoc& from, const SGGeoc& to)
|
||||
{
|
||||
return distanceRad(from, to) * SG_RAD_TO_NM * SG_NM_TO_METER;
|
||||
}
|
||||
|
||||
@@ -53,10 +53,15 @@ public:
|
||||
static bool inverse(const SGGeod& p1, const SGGeod& p2, double& course1,
|
||||
double& course2, double& distance);
|
||||
|
||||
static double courseDeg(const SGGeod& from, const SGGeod& to);
|
||||
static double distanceM(const SGGeod& from, const SGGeod& to);
|
||||
static double distanceNm(const SGGeod& from, const SGGeod& to);
|
||||
|
||||
// Geocentric course/distance computation
|
||||
static void advanceRadM(const SGGeoc& geoc, double course, double distance,
|
||||
SGGeoc& result);
|
||||
static double courseRad(const SGGeoc& from, const SGGeoc& to);
|
||||
static double distanceRad(const SGGeoc& from, const SGGeoc& to);
|
||||
static double distanceM(const SGGeoc& from, const SGGeoc& to);
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,102 @@ SGVec3<T> rndVec3(void)
|
||||
return SGVec3<T>(sg_random(), sg_random(), sg_random());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
TriangleClosestPointIntersectionTest(void)
|
||||
{
|
||||
unsigned nTests = 100000;
|
||||
unsigned failedCount = 0;
|
||||
for (unsigned i = 0; i < nTests; ++i) {
|
||||
// test triangle
|
||||
SGTriangle<T> triangle(rndVec3<T>(), rndVec3<T>(), rndVec3<T>());
|
||||
T triangleEps = 100*SGLimits<T>::epsilon();
|
||||
|
||||
// generate random point in the triangle
|
||||
T u = 4*sg_random() - 2;
|
||||
T v = 4*sg_random() - 2;
|
||||
if (1 < u + v) {
|
||||
v = T(0.5)*(v + 1 - u);
|
||||
u = 1 - v;
|
||||
}
|
||||
u = SGMisc<T>::clip(u, 0, 1);
|
||||
v = SGMisc<T>::clip(v, 0, 1);
|
||||
|
||||
SGVec3<T> testClosest;
|
||||
testClosest = triangle.getBaseVertex();
|
||||
testClosest += u*triangle.getEdge(0) + v*triangle.getEdge(1);
|
||||
|
||||
SGVec3<T> n = triangle.getNormal();
|
||||
SGVec3<T> e0 = triangle.getEdge(0);
|
||||
SGVec3<T> e1 = triangle.getEdge(1);
|
||||
|
||||
// The normals to the edges
|
||||
SGVec3<T> a0 = cross(e0, n);
|
||||
SGVec3<T> a1 = cross(e1 - e0, n);
|
||||
SGVec3<T> a2 = cross(n, e1);
|
||||
|
||||
SGVec3<T> testPoint = testClosest;
|
||||
// Ok, if we are at some edge, go perpandicular to the triangle away
|
||||
if (u == 0) {
|
||||
if (v == 0) {
|
||||
testPoint += sg_random()*a0 + sg_random()*a2;
|
||||
} else if (v == 1) {
|
||||
testPoint += sg_random()*a1 + sg_random()*a2;
|
||||
} else {
|
||||
testPoint += sg_random()*a2;
|
||||
}
|
||||
} else if (u == 1) {
|
||||
testPoint += sg_random()*a0 + sg_random()*a1;
|
||||
} else {
|
||||
if (v == 0) {
|
||||
testPoint += sg_random()*a0;
|
||||
} else if (u + v == 1) {
|
||||
testPoint += sg_random()*a1;
|
||||
}
|
||||
}
|
||||
testPoint += (2*sg_random() - 1)*n;
|
||||
|
||||
// Test the closest point function
|
||||
SGVec3<T> closest = closestPoint(triangle, testPoint);
|
||||
if (!equivalent(closest, testClosest, triangleEps)) {
|
||||
std::cout << "Failed closest point test #" << i
|
||||
<< ": not equivalent!\nu = "
|
||||
<< u << ", v = " << v
|
||||
<< "\ntestPoint = " << testPoint
|
||||
<< ", testClosest = " << testClosest
|
||||
<< ", closest = " << closest << "\n"
|
||||
<< triangle << std::endl;
|
||||
++failedCount;
|
||||
}
|
||||
|
||||
// Test the triangle sphere intersection
|
||||
SGSphere<T> sphere(testPoint, sg_random());
|
||||
bool exactIntersection = intersects(sphere, testClosest);
|
||||
// bool exactIntersection = intersects(sphere, closest);
|
||||
bool sphereTriangleIntersection = intersects(sphere, triangle);
|
||||
|
||||
if (sphereTriangleIntersection != exactIntersection) {
|
||||
std::cout << "Failed triangle sphere intersection test #" << i
|
||||
<< ": not equivalent!\nu = "
|
||||
<< u << ", v = " << v
|
||||
<< "\ntestPoint = " << testPoint
|
||||
<< ", testClosest = " << testClosest
|
||||
<< ", closest = " << closest << "\n"
|
||||
<< triangle << std::endl;
|
||||
++failedCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (nTests < 100*failedCount) {
|
||||
std::cout << "Failed box line intersection tests: " << failedCount
|
||||
<< " tests out of " << nTests
|
||||
<< " went wrong. Abort!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
TriangleLineIntersectionTest(void)
|
||||
@@ -44,6 +140,8 @@ TriangleLineIntersectionTest(void)
|
||||
|
||||
SGTriangle<T> tri(v0, v1, v2);
|
||||
|
||||
T triangleEps = 100*SGLimits<T>::epsilon();
|
||||
|
||||
// generate random coeficients
|
||||
T u = 4*sg_random() - 2;
|
||||
T v = 4*sg_random() - 2;
|
||||
@@ -59,7 +157,7 @@ TriangleLineIntersectionTest(void)
|
||||
|
||||
if (intersects(isectres, tri, lineSegment)) {
|
||||
if (0 <= u && 0 <= v && u+v <= 1 && 0 <= t && t <= 1) {
|
||||
if (!equivalent(isectres, isectpt)) {
|
||||
if (!equivalent(isectres, isectpt, triangleEps)) {
|
||||
std::cout << "Failed line segment intersection test #" << i
|
||||
<< ": not equivalent!\nu = "
|
||||
<< u << ", v = " << v << ", t = " << t
|
||||
@@ -87,7 +185,7 @@ TriangleLineIntersectionTest(void)
|
||||
ray.set(isectpt - t*dir, dir);
|
||||
if (intersects(isectres, tri, ray)) {
|
||||
if (0 <= u && 0 <= v && u+v <= 1 && 0 <= t) {
|
||||
if (!equivalent(isectres, isectpt)) {
|
||||
if (!equivalent(isectres, isectpt, triangleEps)) {
|
||||
std::cout << "Failed ray intersection test #" << i
|
||||
<< ": not equivalent!\nu = "
|
||||
<< u << ", v = " << v << ", t = " << t
|
||||
@@ -422,6 +520,13 @@ main(void)
|
||||
<< "Some of these tests can fail due to roundoff problems...\n"
|
||||
<< "Dont worry if only a few of them fail..." << std::endl;
|
||||
|
||||
sg_srandom(17);
|
||||
|
||||
if (!TriangleClosestPointIntersectionTest<float>())
|
||||
return EXIT_FAILURE;
|
||||
if (!TriangleClosestPointIntersectionTest<double>())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!TriangleLineIntersectionTest<float>())
|
||||
return EXIT_FAILURE;
|
||||
if (!TriangleLineIntersectionTest<double>())
|
||||
|
||||
+464
-28
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
// Copyright (C) 2006-2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -20,40 +20,40 @@
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
intersects(const SGBox<T>& box, const SGSphere<T>& sphere)
|
||||
intersects(const SGSphere<T>& s1, const SGSphere<T>& s2)
|
||||
{
|
||||
if (s1.empty())
|
||||
return false;
|
||||
if (s2.empty())
|
||||
return false;
|
||||
|
||||
T dist = s1.getRadius() + s2.getRadius();
|
||||
return distSqr(s1.getCenter(), s2.getCenter()) <= dist*dist;
|
||||
}
|
||||
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGBox<T1>& box, const SGSphere<T2>& sphere)
|
||||
{
|
||||
if (sphere.empty())
|
||||
return false;
|
||||
// Is more or less trivially included in the next tests
|
||||
// if (box.empty())
|
||||
// return false;
|
||||
|
||||
if (sphere.getCenter().x() < box.getMin().x() - sphere.getRadius())
|
||||
return false;
|
||||
if (sphere.getCenter().y() < box.getMin().y() - sphere.getRadius())
|
||||
return false;
|
||||
if (sphere.getCenter().z() < box.getMin().z() - sphere.getRadius())
|
||||
if (box.empty())
|
||||
return false;
|
||||
|
||||
if (box.getMax().x() + sphere.getRadius() < sphere.getCenter().x())
|
||||
return false;
|
||||
if (box.getMax().y() + sphere.getRadius() < sphere.getCenter().y())
|
||||
return false;
|
||||
if (box.getMax().z() + sphere.getRadius() < sphere.getCenter().z())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
SGVec3<T1> closest = box.getClosestPoint(sphere.getCenter());
|
||||
return distSqr(closest, SGVec3<T1>(sphere.getCenter())) <= sphere.getRadius2();
|
||||
}
|
||||
// make it symmetric
|
||||
template<typename T>
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGSphere<T>& sphere, const SGBox<T>& box)
|
||||
intersects(const SGSphere<T1>& sphere, const SGBox<T2>& box)
|
||||
{ return intersects(box, sphere); }
|
||||
|
||||
|
||||
template<typename T>
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGVec3<T>& v, const SGBox<T>& box)
|
||||
intersects(const SGVec3<T1>& v, const SGBox<T2>& box)
|
||||
{
|
||||
if (v[0] < box.getMin()[0])
|
||||
return false;
|
||||
@@ -69,9 +69,9 @@ intersects(const SGVec3<T>& v, const SGBox<T>& box)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
template<typename T>
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGBox<T>& box, const SGVec3<T>& v)
|
||||
intersects(const SGBox<T1>& box, const SGVec3<T2>& v)
|
||||
{ return intersects(v, box); }
|
||||
|
||||
|
||||
@@ -529,13 +529,427 @@ template<typename T>
|
||||
inline bool
|
||||
intersects(const SGTriangle<T>& tri, const SGLineSegment<T>& lineSegment, T eps = 0)
|
||||
{
|
||||
// FIXME: for now just wrap the othr method. When that has prooven
|
||||
// FIXME: for now just wrap the other method. When that has prooven
|
||||
// well optimized, implement that special case
|
||||
SGVec3<T> dummy;
|
||||
return intersects(dummy, tri, lineSegment, eps);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline SGVec3<T>
|
||||
closestPoint(const SGTriangle<T>& tri, const SGVec3<T>& p)
|
||||
{
|
||||
// This method minimizes the distance function Q(u, v) = || p - x ||
|
||||
// where x is a point in the trialgle given by the vertices v_i
|
||||
// x = v_0 + u*(v_1 - v_0) + v*(v_2 - v_0)
|
||||
// The theoretical analysis is somehow too long for a comment.
|
||||
// May be it is sufficient to see that this code passes all the tests.
|
||||
|
||||
SGVec3<T> off = tri.getBaseVertex() - p;
|
||||
T a = dot(tri.getEdge(0), tri.getEdge(0));
|
||||
T b = dot(tri.getEdge(0), tri.getEdge(1));
|
||||
T c = dot(tri.getEdge(1), tri.getEdge(1));
|
||||
T d = dot(tri.getEdge(0), off);
|
||||
T e = dot(tri.getEdge(1), off);
|
||||
|
||||
T det = a*c - b*b;
|
||||
|
||||
T u = b*e - c*d;
|
||||
T v = b*d - a*e;
|
||||
|
||||
/*
|
||||
// Regions
|
||||
// \2|
|
||||
// \|
|
||||
// |\
|
||||
// 3 |0\ 1
|
||||
//----------
|
||||
// 4 | 5 \ 6
|
||||
*/
|
||||
|
||||
if (u + v <= det) {
|
||||
if (u < 0) {
|
||||
if (v < 0) {
|
||||
// region 4
|
||||
if (d < 0) {
|
||||
if (a <= -d) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0);
|
||||
}
|
||||
} else {
|
||||
if (0 < e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else if (c <= -e) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getBaseVertex() + tri.getEdge(1);
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
return tri.getBaseVertex() + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// region 3
|
||||
if (0 <= e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else if (c <= -e) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getBaseVertex() + tri.getEdge(1);
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
return tri.getBaseVertex() + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
} else if (v < 0) {
|
||||
// region 5
|
||||
if (0 <= d) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else if (a <= -d) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0);
|
||||
}
|
||||
} else {
|
||||
// region 0
|
||||
if (det <= SGLimits<T>::min()) {
|
||||
u = 0;
|
||||
v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else {
|
||||
T invDet = 1/det;
|
||||
u *= invDet;
|
||||
v *= invDet;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (u < 0) {
|
||||
// region 2
|
||||
T tmp0 = b + d;
|
||||
T tmp1 = c + e;
|
||||
if (tmp0 < tmp1) {
|
||||
T numer = tmp1 - tmp0;
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else {
|
||||
u = numer/denom;
|
||||
v = 1 - u;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
|
||||
}
|
||||
} else {
|
||||
if (tmp1 <= 0) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getBaseVertex() + tri.getEdge(1);
|
||||
} else if (0 <= e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
return tri.getBaseVertex() + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
} else if (v < 0) {
|
||||
// region 6
|
||||
T tmp0 = b + e;
|
||||
T tmp1 = a + d;
|
||||
if (tmp0 < tmp1) {
|
||||
T numer = tmp1 - tmp0;
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getBaseVertex() + tri.getEdge(1);
|
||||
} else {
|
||||
v = numer/denom;
|
||||
u = 1 - v;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
|
||||
}
|
||||
} else {
|
||||
if (tmp1 < 0) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else if (0 <= d) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// region 1
|
||||
T numer = c + e - b - d;
|
||||
if (numer <= 0) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getVertex(2);
|
||||
} else {
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else {
|
||||
u = numer/denom;
|
||||
v = 1 - u;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
inline SGVec3<T>
|
||||
closestPoint(const SGVec3<T>& p, const SGTriangle<T>& tri)
|
||||
{ return closestPoint(tri, p); }
|
||||
|
||||
template<typename T, typename T2>
|
||||
inline bool
|
||||
intersects(const SGTriangle<T>& tri, const SGSphere<T2>& sphere)
|
||||
{
|
||||
// This method minimizes the distance function Q(u, v) = || p - x ||
|
||||
// where x is a point in the trialgle given by the vertices v_i
|
||||
// x = v_0 + u*(v_1 - v_0) + v*(v_2 - v_0)
|
||||
// The theoretical analysis is somehow too long for a comment.
|
||||
// May be it is sufficient to see that this code passes all the tests.
|
||||
|
||||
SGVec3<T> off = tri.getBaseVertex() - SGVec3<T>(sphere.getCenter());
|
||||
T baseDist2 = dot(off, off);
|
||||
T a = dot(tri.getEdge(0), tri.getEdge(0));
|
||||
T b = dot(tri.getEdge(0), tri.getEdge(1));
|
||||
T c = dot(tri.getEdge(1), tri.getEdge(1));
|
||||
T d = dot(tri.getEdge(0), off);
|
||||
T e = dot(tri.getEdge(1), off);
|
||||
|
||||
T det = a*c - b*b;
|
||||
|
||||
T u = b*e - c*d;
|
||||
T v = b*d - a*e;
|
||||
|
||||
/*
|
||||
// Regions
|
||||
// \2|
|
||||
// \|
|
||||
// |\
|
||||
// 3 |0\ 1
|
||||
//----------
|
||||
// 4 | 5 \ 6
|
||||
*/
|
||||
|
||||
if (u + v <= det) {
|
||||
if (u < 0) {
|
||||
if (v < 0) {
|
||||
// region 4
|
||||
if (d < 0) {
|
||||
if (a <= -d) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
T sqrDist = d*u + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
} else {
|
||||
if (0 < e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else if (c <= -e) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
T sqrDist = e*v + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// region 3
|
||||
if (0 <= e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else if (c <= -e) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
T sqrDist = e*v + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else if (v < 0) {
|
||||
// region 5
|
||||
if (0 <= d) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else if (a <= -d) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
T sqrDist = d*u + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
} else {
|
||||
// region 0
|
||||
if (det <= SGLimits<T>::min()) {
|
||||
// sqrDist = baseDist2;
|
||||
u = 0;
|
||||
v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else {
|
||||
T invDet = 1/det;
|
||||
u *= invDet;
|
||||
v *= invDet;
|
||||
T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e) + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (u < 0) {
|
||||
// region 2
|
||||
T tmp0 = b + d;
|
||||
T tmp1 = c + e;
|
||||
if (tmp0 < tmp1) {
|
||||
T numer = tmp1 - tmp0;
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
u = numer/denom;
|
||||
v = 1 - u;
|
||||
T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e) + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
} else {
|
||||
if (tmp1 <= 0) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else if (0 <= e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
T sqrDist = e*v + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else if (v < 0) {
|
||||
// region 6
|
||||
T tmp0 = b + e;
|
||||
T tmp1 = a + d;
|
||||
if (tmp0 < tmp1) {
|
||||
T numer = tmp1 - tmp0;
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
v = numer/denom;
|
||||
u = 1 - v;
|
||||
T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e)+baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
} else {
|
||||
if (tmp1 < 0) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else if (0 <= d) {
|
||||
// sqrDist = baseDist2;
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
T sqrDist = d*u + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// region 1
|
||||
T numer = c + e - b - d;
|
||||
if (numer <= 0) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
u = numer/denom;
|
||||
v = 1 - u;
|
||||
T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e) + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGSphere<T1>& sphere, const SGTriangle<T2>& tri)
|
||||
{ return intersects(tri, sphere); }
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
intersects(const SGVec3<T>& v, const SGSphere<T>& sphere)
|
||||
@@ -557,9 +971,9 @@ intersects(const SGBox<T>& box, const SGLineSegment<T>& lineSegment)
|
||||
// See Tomas Akeniene - Moeller/Eric Haines: Real Time Rendering
|
||||
|
||||
SGVec3<T> c = lineSegment.getCenter() - box.getCenter();
|
||||
SGVec3<T> w = 0.5*lineSegment.getDirection();
|
||||
SGVec3<T> w = T(0.5)*lineSegment.getDirection();
|
||||
SGVec3<T> v(fabs(w.x()), fabs(w.y()), fabs(w.z()));
|
||||
SGVec3<T> h = 0.5*box.getSize();
|
||||
SGVec3<T> h = T(0.5)*box.getSize();
|
||||
|
||||
if (fabs(c[0]) > v[0] + h[0])
|
||||
return false;
|
||||
@@ -624,4 +1038,26 @@ inline bool
|
||||
intersects(const SGRay<T>& ray, const SGBox<T>& box)
|
||||
{ return intersects(box, ray); }
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGBox<T1>& box1, const SGBox<T2>& box2)
|
||||
{
|
||||
if (box2.getMax()[0] < box1.getMin()[0])
|
||||
return false;
|
||||
if (box1.getMax()[0] < box2.getMin()[0])
|
||||
return false;
|
||||
|
||||
if (box2.getMax()[1] < box1.getMin()[1])
|
||||
return false;
|
||||
if (box1.getMax()[1] < box2.getMin()[1])
|
||||
return false;
|
||||
|
||||
if (box2.getMax()[2] < box1.getMin()[2])
|
||||
return false;
|
||||
if (box1.getMax()[2] < box2.getMin()[2])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,11 @@ public:
|
||||
_start(start),
|
||||
_direction(end - start)
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGLineSegment(const SGLineSegment<S>& lineSegment) :
|
||||
_start(lineSegment.getStart()),
|
||||
_direction(lineSegment.getDirection())
|
||||
{ }
|
||||
|
||||
void set(const SGVec3<T>& start, const SGVec3<T>& end)
|
||||
{ _start = start; _direction = end - start; }
|
||||
@@ -43,6 +48,14 @@ public:
|
||||
SGVec3<T> getCenter() const
|
||||
{ return _start + T(0.5)*_direction; }
|
||||
|
||||
SGLineSegment<T> transform(const SGMatrix<T>& matrix) const
|
||||
{
|
||||
SGLineSegment<T> lineSegment;
|
||||
lineSegment._start = matrix.xformPt(_start);
|
||||
lineSegment._direction = matrix.xformVec(_direction);
|
||||
return lineSegment;
|
||||
}
|
||||
|
||||
private:
|
||||
SGVec3<T> _start;
|
||||
SGVec3<T> _direction;
|
||||
|
||||
@@ -174,16 +174,22 @@ MatrixTest(void)
|
||||
// Create some test matrix
|
||||
SGVec3<T> v0(2, 7, 17);
|
||||
SGQuat<T> q0 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), normalize(v0));
|
||||
SGMatrix<T> m0;
|
||||
SGMatrix<T> m0 = SGMatrix<T>::unit();
|
||||
m0.postMultTranslate(v0);
|
||||
m0.postMultRotate(q0);
|
||||
|
||||
// Check the tqo forms of the inverse for that kind of special matrix
|
||||
SGMatrix<T> m1, m2;
|
||||
invert(m1, m0);
|
||||
m2 = transNeg(m0);
|
||||
// Check the three forms of the inverse for that kind of special matrix
|
||||
SGMatrix<T> m1 = SGMatrix<T>::unit();
|
||||
m1.preMultTranslate(-v0);
|
||||
m1.preMultRotate(inverse(q0));
|
||||
|
||||
SGMatrix<T> m2, m3;
|
||||
invert(m2, m0);
|
||||
m3 = transNeg(m0);
|
||||
if (!equivalent(m1, m2))
|
||||
return false;
|
||||
if (!equivalent(m2, m3))
|
||||
return false;
|
||||
|
||||
// Check matrix multiplication and inversion
|
||||
if (!equivalent(m0*m1, SGMatrix<T>::unit()))
|
||||
@@ -194,6 +200,10 @@ MatrixTest(void)
|
||||
return false;
|
||||
if (!equivalent(m2*m0, SGMatrix<T>::unit()))
|
||||
return false;
|
||||
if (!equivalent(m0*m3, SGMatrix<T>::unit()))
|
||||
return false;
|
||||
if (!equivalent(m3*m0, SGMatrix<T>::unit()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -202,10 +212,10 @@ bool
|
||||
GeodesyTest(void)
|
||||
{
|
||||
// We know that the values are on the order of 1
|
||||
double epsDeg = 10*SGLimits<double>::epsilon();
|
||||
double epsDeg = 10*360*SGLimits<double>::epsilon();
|
||||
// For the altitude values we need to tolerate relative errors in the order
|
||||
// of the radius
|
||||
double epsM = 1e6*SGLimits<double>::epsilon();
|
||||
double epsM = 10*6e6*SGLimits<double>::epsilon();
|
||||
|
||||
SGVec3<double> cart0, cart1;
|
||||
SGGeod geod0, geod1;
|
||||
|
||||
@@ -184,8 +184,15 @@ public:
|
||||
template<typename S>
|
||||
SGMatrix& preMultTranslate(const SGVec3<S>& t)
|
||||
{
|
||||
for (unsigned i = 0; i < SGMatrix<T>::nCols-1; ++i)
|
||||
(*this)(i,3) += T(t(i));
|
||||
for (unsigned i = 0; i < 3; ++i) {
|
||||
T tmp = T(t(i));
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
(*this)(i,0) += tmp*(*this)(3,0);
|
||||
(*this)(i,1) += tmp*(*this)(3,1);
|
||||
(*this)(i,2) += tmp*(*this)(3,2);
|
||||
(*this)(i,3) += tmp*(*this)(3,3);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template<typename S>
|
||||
@@ -193,7 +200,7 @@ public:
|
||||
{
|
||||
SGVec4<T> col3((*this)(0,3), (*this)(1,3), (*this)(2,3), (*this)(3,3));
|
||||
for (unsigned i = 0; i < SGMatrix<T>::nCols-1; ++i) {
|
||||
SGVec4<T> tmp((*this)(0,3), (*this)(1,3), (*this)(2,3), (*this)(3,3));
|
||||
SGVec4<T> tmp((*this)(0,i), (*this)(1,i), (*this)(2,i), (*this)(3,i));
|
||||
col3 += T(t(i))*tmp;
|
||||
}
|
||||
(*this)(0,3) = col3(0); (*this)(1,3) = col3(1);
|
||||
|
||||
@@ -23,14 +23,25 @@ class SGPlane {
|
||||
public:
|
||||
SGPlane()
|
||||
{ }
|
||||
SGPlane(const SGVec3<T>& normal, T dist) :
|
||||
SGPlane(const SGVec3<T>& normal, const T& dist) :
|
||||
_normal(normal), _dist(dist)
|
||||
{ }
|
||||
SGPlane(const SGVec3<T>& normal, const SGVec3<T>& point) :
|
||||
_normal(normal), _dist(-dot(normal, point))
|
||||
{ }
|
||||
SGPlane(const SGVec3<T> vertices[3]) :
|
||||
_normal(normalize(cross(vertices[1] - vertices[0],
|
||||
vertices[2] - vertices[0]))),
|
||||
_dist(-dot(_normal, vertices[0]))
|
||||
{ }
|
||||
SGPlane(const SGVec3<T>& v0, const SGVec3<T>& v1, const SGVec3<T>& v2) :
|
||||
_normal(normalize(cross(v1 - v0, v2 - v0))),
|
||||
_dist(-dot(_normal, v0))
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGPlane(const SGPlane<S>& plane) :
|
||||
_normal(plane.getNormal()), _dist(plane.getDist())
|
||||
{ }
|
||||
|
||||
void setNormal(const SGVec3<T>& normal)
|
||||
{ _normal = normal; }
|
||||
@@ -42,6 +53,10 @@ public:
|
||||
const T& getDist() const
|
||||
{ return _dist; }
|
||||
|
||||
/// Return a point on the plane
|
||||
SGVec3<T> getPointOnPlane() const
|
||||
{ return -_dist*_normal; }
|
||||
|
||||
/// That is the distance where we measure positive in direction of the normal
|
||||
T getPositiveDist() const
|
||||
{ return -_dist; }
|
||||
|
||||
+52
-110
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
// Copyright (C) 2006-2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -26,42 +26,13 @@
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Quat>
|
||||
#endif
|
||||
|
||||
/// Quaternion Class
|
||||
template<typename T>
|
||||
struct SGQuatStorage {
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[4]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[4]
|
||||
{ return _data; }
|
||||
|
||||
void osg() const
|
||||
{ }
|
||||
|
||||
private:
|
||||
T _data[4];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGQuatStorage<double> : public osg::Quat {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const double (&data(void) const)[4]
|
||||
{ return osg::Quat::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
double (&data(void))[4]
|
||||
{ return osg::Quat::_v; }
|
||||
|
||||
const osg::Quat& osg() const
|
||||
{ return *this; }
|
||||
osg::Quat& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
/// 3D Vector Class
|
||||
template<typename T>
|
||||
class SGQuat : protected SGQuatStorage<T> {
|
||||
class SGQuat {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
@@ -84,8 +55,6 @@ public:
|
||||
/// make sure it has at least 4 elements
|
||||
explicit SGQuat(const T* d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
explicit SGQuat(const osg::Quat& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
|
||||
/// Return a unit quaternion
|
||||
static SGQuat unit(void)
|
||||
@@ -158,48 +127,11 @@ public:
|
||||
static SGQuat fromLonLat(const SGGeod& geod)
|
||||
{ return fromLonLatRad(geod.getLongitudeRad(), geod.getLatitudeRad()); }
|
||||
|
||||
/// Return a quaternion rotation from the earth centered to the
|
||||
/// OpenGL/viewer horizontal local frame from given longitude and latitude.
|
||||
/// This frame matches the usual OpenGL axis directions. That is the target
|
||||
/// frame has an x-axis pointing eastwards, y-axis pointing up and y z-axis
|
||||
/// pointing south.
|
||||
static SGQuat viewHLRad(T lon, T lat)
|
||||
{
|
||||
// That bails down to a 3-2-1 euler sequence lon+pi/2, 0, -lat-pi
|
||||
// what is here is again the hand optimized version ...
|
||||
SGQuat q;
|
||||
T xd2 = -T(0.5)*lat - T(0.5)*SGMisc<T>::pi();
|
||||
T zd2 = T(0.5)*lon + T(0.25)*SGMisc<T>::pi();
|
||||
T Szd2 = sin(zd2);
|
||||
T Sxd2 = sin(xd2);
|
||||
T Czd2 = cos(zd2);
|
||||
T Cxd2 = cos(xd2);
|
||||
q.w() = Cxd2*Czd2;
|
||||
q.x() = Sxd2*Czd2;
|
||||
q.y() = Sxd2*Szd2;
|
||||
q.z() = Cxd2*Szd2;
|
||||
return q;
|
||||
}
|
||||
/// Like the above provided for convenience
|
||||
static SGQuat viewHLDeg(T lon, T lat)
|
||||
{ return viewHLRad(SGMisc<T>::deg2rad(lon), SGMisc<T>::deg2rad(lat)); }
|
||||
/// Like the above provided for convenience
|
||||
static SGQuat viewHL(const SGGeod& geod)
|
||||
{ return viewHLRad(geod.getLongitudeRad(), geod.getLatitudeRad()); }
|
||||
|
||||
/// Convert a quaternion rotation from the simulation frame
|
||||
/// to the view (OpenGL) frame. That is it just swaps the axis part of
|
||||
/// this current quaternion.
|
||||
/// That proves useful when you want to use the euler 3-2-1 sequence
|
||||
/// for the usual heading/pitch/roll sequence within the context of
|
||||
/// OpenGL/viewer frames.
|
||||
static SGQuat simToView(const SGQuat& q)
|
||||
{ return SGQuat(q.y(), -q.z(), -q.x(), q.w()); }
|
||||
|
||||
/// Create a quaternion from the angle axis representation
|
||||
static SGQuat fromAngleAxis(T angle, const SGVec3<T>& axis)
|
||||
{
|
||||
T angle2 = 0.5*angle;
|
||||
T angle2 = T(0.5)*angle;
|
||||
return fromRealImag(cos(angle2), T(sin(angle2))*axis);
|
||||
}
|
||||
|
||||
@@ -213,34 +145,36 @@ public:
|
||||
{
|
||||
T nAxis = norm(axis);
|
||||
if (nAxis <= SGLimits<T>::min())
|
||||
return SGQuat(1, 0, 0, 0);
|
||||
T angle2 = 0.5*nAxis;
|
||||
return SGQuat::unit();
|
||||
T angle2 = T(0.5)*nAxis;
|
||||
return fromRealImag(cos(angle2), T(sin(angle2)/nAxis)*axis);
|
||||
}
|
||||
|
||||
/// Return a quaternion that rotates the from vector onto the to vector.
|
||||
static SGQuat fromRotateTo(const SGVec3<T>& from, const SGVec3<T>& to)
|
||||
{
|
||||
T nfrom = norm(from);
|
||||
T nto = norm(to);
|
||||
if (nfrom < SGLimits<T>::min() || nto < SGLimits<T>::min())
|
||||
if (nfrom <= SGLimits<T>::min() || nto <= SGLimits<T>::min())
|
||||
return SGQuat::unit();
|
||||
|
||||
return SGQuat::fromRotateToNorm((1/nfrom)*from, (1/nto)*to);
|
||||
}
|
||||
|
||||
// FIXME more finegrained error behavour.
|
||||
/// Return a quaternion that rotates v1 onto the i1-th unit vector
|
||||
/// and v2 into a plane that is spanned by the i2-th and i1-th unit vector.
|
||||
static SGQuat fromRotateTo(const SGVec3<T>& v1, unsigned i1,
|
||||
const SGVec3<T>& v2, unsigned i2)
|
||||
{
|
||||
T nrmv1 = norm(v1);
|
||||
T nrmv2 = norm(v2);
|
||||
if (nrmv1 < SGLimits<T>::min() || nrmv2 < SGLimits<T>::min())
|
||||
if (nrmv1 <= SGLimits<T>::min() || nrmv2 <= SGLimits<T>::min())
|
||||
return SGQuat::unit();
|
||||
|
||||
SGVec3<T> nv1 = (1/nrmv1)*v1;
|
||||
SGVec3<T> nv2 = (1/nrmv2)*v2;
|
||||
T dv1v2 = dot(nv1, nv2);
|
||||
if (fabs(fabs(dv1v2)-1) < SGLimits<T>::epsilon())
|
||||
if (fabs(fabs(dv1v2)-1) <= SGLimits<T>::epsilon())
|
||||
return SGQuat::unit();
|
||||
|
||||
// The target vector for the first rotation
|
||||
@@ -261,12 +195,12 @@ public:
|
||||
|
||||
SGVec3<T> tnv2 = q.transform(nv2);
|
||||
T cosang = dot(nto2, tnv2);
|
||||
T cos05ang = T(0.5+0.5*cosang);
|
||||
T cos05ang = T(0.5)+T(0.5)*cosang;
|
||||
if (cos05ang <= 0)
|
||||
cosang = T(0);
|
||||
cosang = 0;
|
||||
cos05ang = sqrt(cos05ang);
|
||||
T sig = dot(nto1, cross(nto2, tnv2));
|
||||
T sin05ang = T(0.5-0.5*cosang);
|
||||
T sin05ang = T(0.5)-T(0.5)*cosang;
|
||||
if (sin05ang <= 0)
|
||||
sin05ang = 0;
|
||||
sin05ang = copysign(sqrt(sin05ang), sig);
|
||||
@@ -329,24 +263,24 @@ public:
|
||||
|
||||
T num = 2*(y()*z() + w()*x());
|
||||
T den = sqrQW - sqrQX - sqrQY + sqrQZ;
|
||||
if (fabs(den) < SGLimits<T>::min() &&
|
||||
fabs(num) < SGLimits<T>::min())
|
||||
if (fabs(den) <= SGLimits<T>::min() &&
|
||||
fabs(num) <= SGLimits<T>::min())
|
||||
xRad = 0;
|
||||
else
|
||||
xRad = atan2(num, den);
|
||||
|
||||
T tmp = 2*(x()*z() - w()*y());
|
||||
if (tmp < -1)
|
||||
yRad = 0.5*SGMisc<T>::pi();
|
||||
else if (1 < tmp)
|
||||
yRad = -0.5*SGMisc<T>::pi();
|
||||
if (tmp <= -1)
|
||||
yRad = T(0.5)*SGMisc<T>::pi();
|
||||
else if (1 <= tmp)
|
||||
yRad = -T(0.5)*SGMisc<T>::pi();
|
||||
else
|
||||
yRad = -asin(tmp);
|
||||
|
||||
num = 2*(x()*y() + w()*z());
|
||||
den = sqrQW + sqrQX - sqrQY - sqrQZ;
|
||||
if (fabs(den) < SGLimits<T>::min() &&
|
||||
fabs(num) < SGLimits<T>::min())
|
||||
if (fabs(den) <= SGLimits<T>::min() &&
|
||||
fabs(num) <= SGLimits<T>::min())
|
||||
zRad = 0;
|
||||
else {
|
||||
T psi = atan2(num, den);
|
||||
@@ -369,14 +303,14 @@ public:
|
||||
void getAngleAxis(T& angle, SGVec3<T>& axis) const
|
||||
{
|
||||
T nrm = norm(*this);
|
||||
if (nrm < SGLimits<T>::min()) {
|
||||
if (nrm <= SGLimits<T>::min()) {
|
||||
angle = 0;
|
||||
axis = SGVec3<T>(0, 0, 0);
|
||||
} else {
|
||||
T rNrm = 1/nrm;
|
||||
angle = acos(SGMisc<T>::max(-1, SGMisc<T>::min(1, rNrm*w())));
|
||||
T sAng = sin(angle);
|
||||
if (fabs(sAng) < SGLimits<T>::min())
|
||||
if (fabs(sAng) <= SGLimits<T>::min())
|
||||
axis = SGVec3<T>(1, 0, 0);
|
||||
else
|
||||
axis = (rNrm/sAng)*imag(*this);
|
||||
@@ -432,17 +366,11 @@ public:
|
||||
{ return data()[3]; }
|
||||
|
||||
/// Get the data pointer
|
||||
using SGQuatStorage<T>::data;
|
||||
|
||||
/// Readonly interface function to ssg's sgQuat/sgdQuat
|
||||
const T (&sg(void) const)[4]
|
||||
{ return data(); }
|
||||
/// Interface function to ssg's sgQuat/sgdQuat
|
||||
T (&sg(void))[4]
|
||||
{ return data(); }
|
||||
|
||||
/// Interface function to osg's Quat*
|
||||
using SGQuatStorage<T>::osg;
|
||||
const T (&data(void) const)[4]
|
||||
{ return _data; }
|
||||
/// Get the data pointer
|
||||
T (&data(void))[4]
|
||||
{ return _data; }
|
||||
|
||||
/// Inplace addition
|
||||
SGQuat& operator+=(const SGQuat& v)
|
||||
@@ -493,10 +421,10 @@ public:
|
||||
{
|
||||
SGQuat deriv;
|
||||
|
||||
deriv.w() = 0.5*(-x()*angVel(0) - y()*angVel(1) - z()*angVel(2));
|
||||
deriv.x() = 0.5*( w()*angVel(0) - z()*angVel(1) + y()*angVel(2));
|
||||
deriv.y() = 0.5*( z()*angVel(0) + w()*angVel(1) - x()*angVel(2));
|
||||
deriv.z() = 0.5*(-y()*angVel(0) + x()*angVel(1) + w()*angVel(2));
|
||||
deriv.w() = T(0.5)*(-x()*angVel(0) - y()*angVel(1) - z()*angVel(2));
|
||||
deriv.x() = T(0.5)*( w()*angVel(0) - z()*angVel(1) + y()*angVel(2));
|
||||
deriv.y() = T(0.5)*( z()*angVel(0) + w()*angVel(1) - x()*angVel(2));
|
||||
deriv.z() = T(0.5)*(-y()*angVel(0) + x()*angVel(1) + w()*angVel(2));
|
||||
|
||||
return deriv;
|
||||
}
|
||||
@@ -521,7 +449,7 @@ private:
|
||||
// in the interval [-pi,pi]. That means that 0.5*angle is in the interval
|
||||
// [-pi/2,pi/2]. But in that range the cosine is allways >= 0.
|
||||
// So we do not need to care for egative roots in the following equation:
|
||||
T cos05ang = sqrt(0.5+0.5*cosang);
|
||||
T cos05ang = sqrt(T(0.5)+T(0.5)*cosang);
|
||||
|
||||
|
||||
// Now our assumption of angles <= 90 deg comes in play.
|
||||
@@ -561,6 +489,8 @@ private:
|
||||
SGQuat q2 = SGQuat::fromRotateToSmaller90Deg(-cosang, -from, to);
|
||||
return q1*q2;
|
||||
}
|
||||
|
||||
T _data[4];
|
||||
};
|
||||
|
||||
/// Unary +, do nothing ...
|
||||
@@ -759,7 +689,7 @@ interpolate(T t, const SGQuat<T>& src, const SGQuat<T>& dst)
|
||||
// need the scales now, if the angle is very small, do linear interpolation
|
||||
// to avoid instabilities
|
||||
T scale0, scale1;
|
||||
if (fabs(o) < SGLimits<T>::epsilon()) {
|
||||
if (fabs(o) <= SGLimits<T>::epsilon()) {
|
||||
scale0 = 1 - t;
|
||||
scale1 = t;
|
||||
} else {
|
||||
@@ -790,4 +720,16 @@ SGQuatd
|
||||
toQuatd(const SGQuatf& v)
|
||||
{ return SGQuatd(v(0), v(1), v(2), v(3)); }
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
inline
|
||||
SGQuatd
|
||||
toSG(const osg::Quat& q)
|
||||
{ return SGQuatd(q[0], q[1], q[2], q[3]); }
|
||||
|
||||
inline
|
||||
osg::Quat
|
||||
toOsg(const SGQuatd& q)
|
||||
{ return osg::Quat(q[0], q[1], q[2], q[3]); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,6 +26,10 @@ public:
|
||||
SGRay(const SGVec3<T>& origin, const SGVec3<T>& dir) :
|
||||
_origin(origin), _direction(dir)
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGRay(const SGRay<S>& ray) :
|
||||
_origin(ray.getOrigin()), _direction(ray.getDirection())
|
||||
{ }
|
||||
|
||||
void set(const SGVec3<T>& origin, const SGVec3<T>& dir)
|
||||
{ _origin = origin; _direction = dir; }
|
||||
|
||||
@@ -28,6 +28,11 @@ public:
|
||||
_center(center),
|
||||
_radius(radius)
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGSphere(const SGSphere<S>& sphere) :
|
||||
_center(sphere.getCenter()),
|
||||
_radius(sphere.getRadius())
|
||||
{ }
|
||||
|
||||
const SGVec3<T>& getCenter() const
|
||||
{ return _center; }
|
||||
@@ -41,7 +46,7 @@ public:
|
||||
T getRadius2() const
|
||||
{ return _radius*_radius; }
|
||||
|
||||
const bool empty() const
|
||||
bool empty() const
|
||||
{ return !valid(); }
|
||||
|
||||
bool valid() const
|
||||
@@ -68,6 +73,65 @@ public:
|
||||
_radius = newRadius;
|
||||
}
|
||||
|
||||
void expandBy(const SGSphere<T>& s)
|
||||
{
|
||||
if (s.empty())
|
||||
return;
|
||||
|
||||
if (empty()) {
|
||||
_center = s.getCenter();
|
||||
_radius = s.getRadius();
|
||||
return;
|
||||
}
|
||||
|
||||
T dist = length(_center - s.getCenter());
|
||||
if (dist <= SGLimits<T>::min()) {
|
||||
_radius = SGMisc<T>::max(_radius, s._radius);
|
||||
return;
|
||||
}
|
||||
|
||||
// already included
|
||||
if (dist + s.getRadius() <= _radius)
|
||||
return;
|
||||
|
||||
// new one includes all
|
||||
if (dist + _radius <= s.getRadius()) {
|
||||
_center = s.getCenter();
|
||||
_radius = s.getRadius();
|
||||
return;
|
||||
}
|
||||
|
||||
T newRadius = T(0.5)*(_radius + dist + s.getRadius());
|
||||
T ratio = (newRadius - _radius) / dist;
|
||||
_radius = newRadius;
|
||||
|
||||
_center[0] += ratio*(s._center[0] - _center[0]);
|
||||
_center[1] += ratio*(s._center[1] - _center[1]);
|
||||
_center[2] += ratio*(s._center[2] - _center[2]);
|
||||
}
|
||||
|
||||
void expandBy(const SGBox<T>& box)
|
||||
{
|
||||
if (box.empty())
|
||||
return;
|
||||
|
||||
if (empty()) {
|
||||
_center = box.getCenter();
|
||||
_radius = T(0.5)*length(box.getSize());
|
||||
return;
|
||||
}
|
||||
|
||||
SGVec3<T> boxCenter = box.getCenter();
|
||||
SGVec3<T> corner;
|
||||
for (unsigned i = 0; i < 3; ++i) {
|
||||
if (_center[i] < boxCenter[i])
|
||||
corner[i] = box.getMax()[i];
|
||||
else
|
||||
corner[i] = box.getMin()[i];
|
||||
}
|
||||
expandBy(corner);
|
||||
}
|
||||
|
||||
private:
|
||||
SGVec3<T> _center;
|
||||
T _radius;
|
||||
|
||||
@@ -41,14 +41,8 @@ public:
|
||||
_d[1] = v[2] - v[0];
|
||||
}
|
||||
|
||||
SGVec3d getCenter() const
|
||||
{
|
||||
SGBoxd box;
|
||||
box.expandBy(_v0);
|
||||
box.expandBy(_v0 + _d[0]);
|
||||
box.expandBy(_v0 + _d[1]);
|
||||
return box.getCenter();
|
||||
}
|
||||
SGVec3<T> getCenter() const
|
||||
{ return _v0 + T(1)/T(3)*(_d[0] + _d[1]); }
|
||||
|
||||
// note that the index is unchecked
|
||||
SGVec3<T> getVertex(unsigned i) const
|
||||
@@ -77,6 +71,16 @@ public:
|
||||
_d[0] = _d[1];
|
||||
_d[1] = tmp;
|
||||
}
|
||||
|
||||
SGTriangle<T> transform(const SGMatrix<T>& matrix) const
|
||||
{
|
||||
SGTriangle<T> triangle;
|
||||
triangle._v0 = matrix.xformPt(_v0);
|
||||
triangle._d[0] = matrix.xformVec(_d[0]);
|
||||
triangle._d[1] = matrix.xformVec(_d[1]);
|
||||
return triangle;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Store one vertex directly, _d is the offset of the other two
|
||||
/// vertices wrt the base vertex
|
||||
|
||||
+56
-68
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
// Copyright (C) 2006-2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -18,62 +18,14 @@
|
||||
#ifndef SGVec2_H
|
||||
#define SGVec2_H
|
||||
|
||||
#if defined ( __CYGWIN__ )
|
||||
#include <ieeefp.h>
|
||||
#endif
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Vec2f>
|
||||
#include <osg/Vec2d>
|
||||
|
||||
template<typename T>
|
||||
struct SGVec2Storage {
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[2]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[2]
|
||||
{ return _data; }
|
||||
|
||||
void osg() const
|
||||
{ }
|
||||
|
||||
private:
|
||||
T _data[2];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec2Storage<float> : public osg::Vec2f {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const float (&data(void) const)[2]
|
||||
{ return osg::Vec2f::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
float (&data(void))[2]
|
||||
{ return osg::Vec2f::_v; }
|
||||
|
||||
const osg::Vec2f& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec2f& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec2Storage<double> : public osg::Vec2d {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const double (&data(void) const)[2]
|
||||
{ return osg::Vec2d::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
double (&data(void))[2]
|
||||
{ return osg::Vec2d::_v; }
|
||||
|
||||
const osg::Vec2d& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec2d& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
/// 2D Vector Class
|
||||
template<typename T>
|
||||
class SGVec2 : protected SGVec2Storage<T> {
|
||||
class SGVec2 {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
@@ -96,9 +48,8 @@ public:
|
||||
/// make sure it has at least 2 elements
|
||||
explicit SGVec2(const T* d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; }
|
||||
explicit SGVec2(const osg::Vec2f& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; }
|
||||
explicit SGVec2(const osg::Vec2d& d)
|
||||
template<typename S>
|
||||
explicit SGVec2(const SGVec2<S>& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; }
|
||||
|
||||
/// Access by index, the index is unchecked
|
||||
@@ -128,18 +79,12 @@ public:
|
||||
T& y(void)
|
||||
{ return data()[1]; }
|
||||
|
||||
/// Get the data pointer
|
||||
using SGVec2Storage<T>::data;
|
||||
|
||||
/// Readonly interface function to ssg's sgVec2/sgdVec2
|
||||
const T (&sg(void) const)[2]
|
||||
{ return data(); }
|
||||
/// Interface function to ssg's sgVec2/sgdVec2
|
||||
T (&sg(void))[2]
|
||||
{ return data(); }
|
||||
|
||||
/// Interface function to osg's Vec2*
|
||||
using SGVec2Storage<T>::osg;
|
||||
/// Access raw data
|
||||
const T (&data(void) const)[2]
|
||||
{ return _data; }
|
||||
/// Access raw data
|
||||
T (&data(void))[2]
|
||||
{ return _data; }
|
||||
|
||||
/// Inplace addition
|
||||
SGVec2& operator+=(const SGVec2& v)
|
||||
@@ -164,6 +109,9 @@ public:
|
||||
{ return SGVec2(1, 0); }
|
||||
static SGVec2 e2(void)
|
||||
{ return SGVec2(0, 1); }
|
||||
|
||||
private:
|
||||
T _data[2];
|
||||
};
|
||||
|
||||
/// Unary +, do nothing ...
|
||||
@@ -292,7 +240,12 @@ template<typename T>
|
||||
inline
|
||||
SGVec2<T>
|
||||
normalize(const SGVec2<T>& v)
|
||||
{ return (1/norm(v))*v; }
|
||||
{
|
||||
T normv = norm(v);
|
||||
if (normv <= SGLimits<T>::min())
|
||||
return SGVec2<T>::zeros();
|
||||
return (1/normv)*v;
|
||||
}
|
||||
|
||||
/// Return true if exactly the same
|
||||
template<typename T>
|
||||
@@ -379,6 +332,18 @@ T
|
||||
distSqr(const SGVec2<T>& v1, const SGVec2<T>& v2)
|
||||
{ SGVec2<T> tmp = v1 - v2; return dot(tmp, tmp); }
|
||||
|
||||
// calculate the projection of u along the direction of d.
|
||||
template<typename T>
|
||||
inline
|
||||
SGVec2<T>
|
||||
projection(const SGVec2<T>& u, const SGVec2<T>& d)
|
||||
{
|
||||
T denom = dot(d, d);
|
||||
T ud = dot(u, d);
|
||||
if (SGLimits<T>::min() < denom) return u;
|
||||
else return d * (dot(u, d) / denom);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<typename T>
|
||||
inline
|
||||
@@ -406,4 +371,27 @@ SGVec2d
|
||||
toVec2d(const SGVec2f& v)
|
||||
{ return SGVec2d(v(0), v(1)); }
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
inline
|
||||
SGVec2d
|
||||
toSG(const osg::Vec2d& v)
|
||||
{ return SGVec2d(v[0], v[1]); }
|
||||
|
||||
inline
|
||||
SGVec2f
|
||||
toSG(const osg::Vec2f& v)
|
||||
{ return SGVec2f(v[0], v[1]); }
|
||||
|
||||
inline
|
||||
osg::Vec2d
|
||||
toOsg(const SGVec2d& v)
|
||||
{ return osg::Vec2d(v[0], v[1]); }
|
||||
|
||||
inline
|
||||
osg::Vec2f
|
||||
toOsg(const SGVec2f& v)
|
||||
{ return osg::Vec2f(v[0], v[1]); }
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+57
-65
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
// Copyright (C) 2006-2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -18,58 +18,14 @@
|
||||
#ifndef SGVec3_H
|
||||
#define SGVec3_H
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/Vec3d>
|
||||
|
||||
template<typename T>
|
||||
struct SGVec3Storage {
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[3]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[3]
|
||||
{ return _data; }
|
||||
|
||||
void osg() const
|
||||
{ }
|
||||
|
||||
private:
|
||||
T _data[3];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec3Storage<float> : public osg::Vec3f {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const float (&data(void) const)[3]
|
||||
{ return osg::Vec3f::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
float (&data(void))[3]
|
||||
{ return osg::Vec3f::_v; }
|
||||
|
||||
const osg::Vec3f& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec3f& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec3Storage<double> : public osg::Vec3d {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const double (&data(void) const)[3]
|
||||
{ return osg::Vec3d::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
double (&data(void))[3]
|
||||
{ return osg::Vec3d::_v; }
|
||||
|
||||
const osg::Vec3d& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec3d& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
/// 3D Vector Class
|
||||
template<typename T>
|
||||
class SGVec3 : protected SGVec3Storage<T> {
|
||||
class SGVec3 {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
@@ -92,9 +48,8 @@ public:
|
||||
/// make sure it has at least 3 elements
|
||||
explicit SGVec3(const T* d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
||||
explicit SGVec3(const osg::Vec3f& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
||||
explicit SGVec3(const osg::Vec3d& d)
|
||||
template<typename S>
|
||||
explicit SGVec3(const SGVec3<S>& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
||||
explicit SGVec3(const SGVec2<T>& v2, const T& v3 = 0)
|
||||
{ data()[0] = v2[0]; data()[1] = v2[1]; data()[2] = v3; }
|
||||
@@ -132,18 +87,12 @@ public:
|
||||
T& z(void)
|
||||
{ return data()[2]; }
|
||||
|
||||
/// Get the data pointer
|
||||
using SGVec3Storage<T>::data;
|
||||
|
||||
/// Readonly interface function to ssg's sgVec3/sgdVec3
|
||||
const T (&sg(void) const)[3]
|
||||
{ return data(); }
|
||||
/// Interface function to ssg's sgVec3/sgdVec3
|
||||
T (&sg(void))[3]
|
||||
{ return data(); }
|
||||
|
||||
/// Interface function to osg's Vec3*
|
||||
using SGVec3Storage<T>::osg;
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[3]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[3]
|
||||
{ return _data; }
|
||||
|
||||
/// Inplace addition
|
||||
SGVec3& operator+=(const SGVec3& v)
|
||||
@@ -177,6 +126,9 @@ public:
|
||||
/// Constructor. Initialize by a geocentric coordinate
|
||||
/// Note that this conversion is relatively expensive to compute
|
||||
static SGVec3 fromGeoc(const SGGeoc& geoc);
|
||||
|
||||
private:
|
||||
T _data[3];
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -400,12 +352,18 @@ perpendicular(const SGVec3<T>& v)
|
||||
}
|
||||
}
|
||||
|
||||
/// The euclidean norm of the vector, that is what most people call length
|
||||
/// Construct a unit vector in the given direction.
|
||||
/// or the zero vector if the input vector is zero.
|
||||
template<typename T>
|
||||
inline
|
||||
SGVec3<T>
|
||||
normalize(const SGVec3<T>& v)
|
||||
{ return (1/norm(v))*v; }
|
||||
{
|
||||
T normv = norm(v);
|
||||
if (normv <= SGLimits<T>::min())
|
||||
return SGVec3<T>::zeros();
|
||||
return (1/normv)*v;
|
||||
}
|
||||
|
||||
/// Return true if exactly the same
|
||||
template<typename T>
|
||||
@@ -496,6 +454,18 @@ T
|
||||
distSqr(const SGVec3<T>& v1, const SGVec3<T>& v2)
|
||||
{ SGVec3<T> tmp = v1 - v2; return dot(tmp, tmp); }
|
||||
|
||||
// calculate the projection of u along the direction of d.
|
||||
template<typename T>
|
||||
inline
|
||||
SGVec3<T>
|
||||
projection(const SGVec3<T>& u, const SGVec3<T>& d)
|
||||
{
|
||||
T denom = dot(d, d);
|
||||
T ud = dot(u, d);
|
||||
if (SGLimits<T>::min() < denom) return u;
|
||||
else return d * (dot(u, d) / denom);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<typename T>
|
||||
inline
|
||||
@@ -524,4 +494,26 @@ SGVec3d
|
||||
toVec3d(const SGVec3f& v)
|
||||
{ return SGVec3d(v(0), v(1), v(2)); }
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
inline
|
||||
SGVec3d
|
||||
toSG(const osg::Vec3d& v)
|
||||
{ return SGVec3d(v[0], v[1], v[2]); }
|
||||
|
||||
inline
|
||||
SGVec3f
|
||||
toSG(const osg::Vec3f& v)
|
||||
{ return SGVec3f(v[0], v[1], v[2]); }
|
||||
|
||||
inline
|
||||
osg::Vec3d
|
||||
toOsg(const SGVec3d& v)
|
||||
{ return osg::Vec3d(v[0], v[1], v[2]); }
|
||||
|
||||
inline
|
||||
osg::Vec3f
|
||||
toOsg(const SGVec3f& v)
|
||||
{ return osg::Vec3f(v[0], v[1], v[2]); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+55
-65
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
// Copyright (C) 2006-2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -18,58 +18,14 @@
|
||||
#ifndef SGVec4_H
|
||||
#define SGVec4_H
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Vec4f>
|
||||
#include <osg/Vec4d>
|
||||
|
||||
template<typename T>
|
||||
struct SGVec4Storage {
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[4]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[4]
|
||||
{ return _data; }
|
||||
|
||||
void osg() const
|
||||
{ }
|
||||
|
||||
private:
|
||||
T _data[4];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec4Storage<float> : public osg::Vec4f {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const float (&data(void) const)[4]
|
||||
{ return osg::Vec4f::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
float (&data(void))[4]
|
||||
{ return osg::Vec4f::_v; }
|
||||
|
||||
const osg::Vec4f& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec4f& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec4Storage<double> : public osg::Vec4d {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const double (&data(void) const)[4]
|
||||
{ return osg::Vec4d::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
double (&data(void))[4]
|
||||
{ return osg::Vec4d::_v; }
|
||||
|
||||
const osg::Vec4d& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec4d& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
/// 4D Vector Class
|
||||
template<typename T>
|
||||
class SGVec4 : protected SGVec4Storage<T> {
|
||||
class SGVec4 {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
@@ -92,14 +48,12 @@ public:
|
||||
/// make sure it has at least 3 elements
|
||||
explicit SGVec4(const T* d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
explicit SGVec4(const osg::Vec4f& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
explicit SGVec4(const osg::Vec4d& d)
|
||||
template<typename S>
|
||||
explicit SGVec4(const SGVec4<S>& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
explicit SGVec4(const SGVec3<T>& v3, const T& v4 = 0)
|
||||
{ data()[0] = v3[0]; data()[1] = v3[1]; data()[2] = v3[2]; data()[3] = v4; }
|
||||
|
||||
|
||||
/// Access by index, the index is unchecked
|
||||
const T& operator()(unsigned i) const
|
||||
{ return data()[i]; }
|
||||
@@ -139,18 +93,12 @@ public:
|
||||
T& w(void)
|
||||
{ return data()[3]; }
|
||||
|
||||
/// Get the data pointer
|
||||
using SGVec4Storage<T>::data;
|
||||
|
||||
/// Readonly interface function to ssg's sgVec4/sgdVec4
|
||||
const T (&sg(void) const)[4]
|
||||
{ return data(); }
|
||||
/// Interface function to ssg's sgVec4/sgdVec4
|
||||
T (&sg(void))[4]
|
||||
{ return data(); }
|
||||
|
||||
/// Interface function to osg's Vec4*
|
||||
using SGVec4Storage<T>::osg;
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[4]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[4]
|
||||
{ return _data; }
|
||||
|
||||
/// Inplace addition
|
||||
SGVec4& operator+=(const SGVec4& v)
|
||||
@@ -179,6 +127,9 @@ public:
|
||||
{ return SGVec4(0, 0, 1, 0); }
|
||||
static SGVec4 e4(void)
|
||||
{ return SGVec4(0, 0, 0, 1); }
|
||||
|
||||
private:
|
||||
T _data[4];
|
||||
};
|
||||
|
||||
/// Unary +, do nothing ...
|
||||
@@ -337,7 +288,12 @@ template<typename T>
|
||||
inline
|
||||
SGVec4<T>
|
||||
normalize(const SGVec4<T>& v)
|
||||
{ return (1/norm(v))*v; }
|
||||
{
|
||||
T normv = norm(v);
|
||||
if (normv <= SGLimits<T>::min())
|
||||
return SGVec4<T>::zeros();
|
||||
return (1/normv)*v;
|
||||
}
|
||||
|
||||
/// Return true if exactly the same
|
||||
template<typename T>
|
||||
@@ -432,6 +388,18 @@ T
|
||||
distSqr(const SGVec4<T>& v1, const SGVec4<T>& v2)
|
||||
{ SGVec4<T> tmp = v1 - v2; return dot(tmp, tmp); }
|
||||
|
||||
// calculate the projection of u along the direction of d.
|
||||
template<typename T>
|
||||
inline
|
||||
SGVec4<T>
|
||||
projection(const SGVec4<T>& u, const SGVec4<T>& d)
|
||||
{
|
||||
T denom = dot(d, d);
|
||||
T ud = dot(u, d);
|
||||
if (SGLimits<T>::min() < denom) return u;
|
||||
else return d * (dot(u, d) / denom);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<typename T>
|
||||
inline
|
||||
@@ -460,4 +428,26 @@ SGVec4d
|
||||
toVec4d(const SGVec4f& v)
|
||||
{ return SGVec4d(v(0), v(1), v(2), v(3)); }
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
inline
|
||||
SGVec4d
|
||||
toSG(const osg::Vec4d& v)
|
||||
{ return SGVec4d(v[0], v[1], v[2], v[3]); }
|
||||
|
||||
inline
|
||||
SGVec4f
|
||||
toSG(const osg::Vec4f& v)
|
||||
{ return SGVec4f(v[0], v[1], v[2], v[3]); }
|
||||
|
||||
inline
|
||||
osg::Vec4d
|
||||
toOsg(const SGVec4d& v)
|
||||
{ return osg::Vec4d(v[0], v[1], v[2], v[3]); }
|
||||
|
||||
inline
|
||||
osg::Vec4f
|
||||
toOsg(const SGVec4f& v)
|
||||
{ return osg::Vec4f(v[0], v[1], v[2], v[3]); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Executable
+105
@@ -0,0 +1,105 @@
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2009 Frederic Bouvier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SIMGEAR_BEZIERCURVE_HXX
|
||||
#define SIMGEAR_BEZIERCURVE_HXX 1
|
||||
|
||||
#include <list>
|
||||
using std::list;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
template<class T>
|
||||
class BezierCurve {
|
||||
public:
|
||||
typedef list<T> PointList;
|
||||
|
||||
BezierCurve() : mMaxSubdiv( 3 ) {}
|
||||
BezierCurve( size_t aMaxSubdiv )
|
||||
: mMaxSubdiv( aMaxSubdiv ) {}
|
||||
BezierCurve( const T &p1, const T &p2, const T &p3, size_t aMaxSubdiv = 3 )
|
||||
: mMaxSubdiv( aMaxSubdiv ) {
|
||||
subdivide( p1, p2, p3 );
|
||||
}
|
||||
BezierCurve( const T &p1, const T &p2, const T &p3, const T &p4, size_t aMaxSubdiv = 3 )
|
||||
: mMaxSubdiv( aMaxSubdiv ) {
|
||||
subdivide( p1, p2, p3, p4 );
|
||||
}
|
||||
|
||||
void subdivide( const T &p1, const T &p2, const T &p3 ) {
|
||||
mPointList.clear();
|
||||
mPointList.push_back( p1 );
|
||||
recursiveSubdivide( p1, p2, p3, 1 );
|
||||
mPointList.push_back( p3 );
|
||||
}
|
||||
|
||||
void subdivide( const T &p1, const T &p2, const T &p3, const T &p4 ) {
|
||||
mPointList.clear();
|
||||
mPointList.push_back( p1 );
|
||||
recursiveSubdivide( p1, p2, p3, p4, 1 );
|
||||
mPointList.push_back( p4 );
|
||||
}
|
||||
|
||||
void setMaxSubdiv( size_t aMaxSubdiv ) { mMaxSubdiv = aMaxSubdiv; }
|
||||
void getMaxSubdiv() const { return mMaxSubdiv; }
|
||||
PointList &pointList() { return mPointList; }
|
||||
const PointList &pointList() const { return mPointList; }
|
||||
|
||||
private:
|
||||
T midPoint( const T &p1, const T &p2 ) {
|
||||
return ( p1 + p2 ) / 2;
|
||||
}
|
||||
bool recursiveSubdivide( const T &p1, const T &p2, const T &p3, size_t l ) {
|
||||
if ( l > mMaxSubdiv )
|
||||
return false;
|
||||
|
||||
T p12 = midPoint( p1, p2 ),
|
||||
p23 = midPoint( p2, p3 ),
|
||||
p123 = midPoint( p12, p23 );
|
||||
recursiveSubdivide( p1, p12, p123, l + 1 );
|
||||
mPointList.push_back( p123 );
|
||||
recursiveSubdivide( p123, p23, p3, l + 1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool recursiveSubdivide( const T &p1, const T &p2, const T &p3, const T &p4, size_t l ) {
|
||||
if ( l > mMaxSubdiv )
|
||||
return false;
|
||||
|
||||
T p12 = midPoint( p1, p2 ),
|
||||
p23 = midPoint( p2, p3 ),
|
||||
p34 = midPoint( p3, p4 ),
|
||||
p123 = midPoint( p12, p23 ),
|
||||
p234 = midPoint( p23, p34 ),
|
||||
p1234 = midPoint( p123, p234 );
|
||||
recursiveSubdivide( p1, p12, p123, p1234, l + 1 );
|
||||
mPointList.push_back( p1234 );
|
||||
recursiveSubdivide( p1234, p234, p34, p4, l + 1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
PointList mPointList;
|
||||
size_t mMaxSubdiv;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,9 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
@@ -33,6 +36,8 @@
|
||||
|
||||
#include "interpolater.hxx"
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
using std::string;
|
||||
|
||||
// Constructor -- starts with an empty table.
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include "simgear/structure/SGReferenced.hxx"
|
||||
#include <simgear/structure/SGReferenced.hxx>
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
class Point3D;
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
+18
-16
@@ -29,6 +29,20 @@
|
||||
#include "vector.hxx"
|
||||
|
||||
|
||||
// calculate the projection, p, of u along the direction of d.
|
||||
void sgProjection(sgVec3 p, const sgVec3 u, const sgVec3 d){
|
||||
double denom = sgScalarProductVec3(d,d);
|
||||
if (denom == 0.) sgCopyVec3(p, u);
|
||||
else sgScaleVec3(p, d, sgScalarProductVec3(u,d) / denom);
|
||||
}
|
||||
|
||||
// Same thing, except using double precision
|
||||
void sgProjection(sgdVec3 p, const sgdVec3 u, const sgdVec3 d){
|
||||
double denom = sgdScalarProductVec3(d,d);
|
||||
if (denom == 0.) sgdCopyVec3(p, u);
|
||||
else sgdScaleVec3(p, d, sgdScalarProductVec3(u,d) / denom);
|
||||
}
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the closest point (p1) on the line
|
||||
void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0,
|
||||
@@ -40,8 +54,7 @@ void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0,
|
||||
sgSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) );
|
||||
sgProjection(u1, u, d);
|
||||
|
||||
// calculate the point p1 along the line that is closest to p
|
||||
// p0 = p1 + u1
|
||||
@@ -60,12 +73,7 @@ void sgdClosestPointToLine( sgdVec3 p1, const sgdVec3 p, const sgdVec3 p0,
|
||||
sgdSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
double ud = sgdScalarProductVec3(u, d);
|
||||
double dd = sgdScalarProductVec3(d, d);
|
||||
double tmp = ud / dd;
|
||||
|
||||
sgdScaleVec3(u1, d, tmp);;
|
||||
sgProjection(u1, u, d);
|
||||
|
||||
// calculate the point p1 along the line that is closest to p
|
||||
// p0 = p1 + u1
|
||||
@@ -84,8 +92,7 @@ double sgClosestPointToLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
||||
sgSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) );
|
||||
sgProjection(u1, u, d);
|
||||
|
||||
// v = u - u1 = vector from closest point on line, p1, to the
|
||||
// original point, p.
|
||||
@@ -106,12 +113,7 @@ double sgdClosestPointToLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
||||
sgdSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
double ud = sgdScalarProductVec3(u, d);
|
||||
double dd = sgdScalarProductVec3(d, d);
|
||||
double tmp = ud / dd;
|
||||
|
||||
sgdScaleVec3(u1, d, tmp);;
|
||||
sgProjection(u1, u, d);
|
||||
|
||||
// v = u - u1 = vector from closest point on line, p1, to the
|
||||
// original point, p.
|
||||
|
||||
+11
-1
@@ -38,7 +38,17 @@
|
||||
|
||||
|
||||
/**
|
||||
* Map a vector onto a plane.
|
||||
* calculate the projection, p, of u along the direction of d.
|
||||
* @param p (out) the projection
|
||||
* @param u (in) the vector to be projected
|
||||
* @param d (in) the direction onto which we project
|
||||
*/
|
||||
void sgProjection(sgVec3 p, const sgVec3 u, const sgVec3 d);
|
||||
void sgProjection(sgdVec3 p, const sgdVec3 u, const sgdVec3 d);
|
||||
|
||||
|
||||
/**
|
||||
* Map i.e. project a vector onto a plane.
|
||||
* @param normal (in) normal vector for the plane
|
||||
* @param v0 (in) a point on the plane
|
||||
* @param vec (in) the vector to map onto the plane
|
||||
|
||||
@@ -24,13 +24,13 @@ libsgmisc_a_SOURCES = \
|
||||
interpolator.cxx \
|
||||
PathOptions.cxx
|
||||
|
||||
noinst_PROGRAMS = tabbed_value_test swap_test
|
||||
#noinst_PROGRAMS = tabbed_value_test swap_test
|
||||
|
||||
tabbed_value_test_SOURCES = tabbed_values_test.cxx
|
||||
tabbed_value_test_LDADD = \
|
||||
libsgmisc.a \
|
||||
$(top_builddir)/simgear/xml/libsgxml.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a
|
||||
#tabbed_value_test_SOURCES = tabbed_values_test.cxx
|
||||
#tabbed_value_test_LDADD = \
|
||||
# libsgmisc.a \
|
||||
# $(top_builddir)/simgear/xml/libsgxml.a \
|
||||
# $(top_builddir)/simgear/debug/libsgdebug.a
|
||||
|
||||
$(top_builddir)/simgear/xml/libsgxml.a:
|
||||
cd $(top_builddir)/simgear/xml && $(MAKE) $(AM_MAKEFLAGS) libsgxml.a
|
||||
@@ -38,6 +38,6 @@ $(top_builddir)/simgear/xml/libsgxml.a:
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a:
|
||||
cd $(top_builddir)/simgear/debug && $(MAKE) $(AM_MAKEFLAGS) libsgdebug.a
|
||||
|
||||
swap_test_SOURCES = swap_test.cpp
|
||||
#swap_test_SOURCES = swap_test.cpp
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include "interpolator.hxx"
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
void SGInterpolator::addNew(SGPropertyNode* prop, int nPoints)
|
||||
{
|
||||
// Set the property type to a double, if it isn't already, and
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/stat.h>
|
||||
#if defined( _MSC_VER) || defined(__MINGW32__)
|
||||
#ifdef _WIN32
|
||||
# include <direct.h>
|
||||
#endif
|
||||
#include "sg_path.hxx"
|
||||
@@ -42,7 +42,7 @@
|
||||
static const char sgDirPathSep = '/';
|
||||
static const char sgDirPathSepBad = '\\';
|
||||
|
||||
#if defined( WIN32 ) && !defined(__CYGWIN__)
|
||||
#ifdef _WIN32
|
||||
static const char sgSearchPathSep = ';';
|
||||
#else
|
||||
static const char sgSearchPathSep = ':';
|
||||
@@ -181,7 +181,7 @@ bool SGPath::exists() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined( _MSC_VER) || defined(__MINGW32__)
|
||||
#ifdef _WIN32
|
||||
# define sgMkDir(d,m) _mkdir(d)
|
||||
#else
|
||||
# define sgMkDir(d,m) mkdir(d,m)
|
||||
@@ -199,7 +199,7 @@ int SGPath::create_dir( mode_t mode ) {
|
||||
unsigned int i = 1;
|
||||
SGPath dir = absolute ? string( 1, sgDirPathSep ) : "";
|
||||
dir.concat( path_elements[0] );
|
||||
#if defined( _MSC_VER) || defined(__MINGW32__)
|
||||
#ifdef _WIN32
|
||||
if ( dir.str().find(':') != string::npos && path_elements.size() >= 2 ) {
|
||||
dir.append( path_elements[1] );
|
||||
i = 2;
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
#include "strutils.hxx"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace simgear {
|
||||
namespace strutils {
|
||||
|
||||
|
||||
@@ -30,16 +30,12 @@
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <vector>
|
||||
using std::vector;
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace simgear {
|
||||
namespace strutils {
|
||||
namespace strutils {
|
||||
|
||||
// /**
|
||||
// * atof() wrapper for "string" type
|
||||
@@ -64,9 +60,9 @@ namespace simgear {
|
||||
* @param s String to strip.
|
||||
* @return The stripped string.
|
||||
*/
|
||||
string lstrip( const string& s );
|
||||
string rstrip( const string& s );
|
||||
string strip( const string& s );
|
||||
std::string lstrip( const std::string& s );
|
||||
std::string rstrip( const std::string& s );
|
||||
std::string strip( const std::string& s );
|
||||
|
||||
/**
|
||||
* Split a string into a words using 'sep' as the delimiter string.
|
||||
@@ -79,12 +75,12 @@ namespace simgear {
|
||||
* resulting in at most maxsplit+1 words.
|
||||
* @return Array of words.
|
||||
*/
|
||||
vector<string>
|
||||
split( const string& s,
|
||||
std::vector<std::string>
|
||||
split( const std::string& s,
|
||||
const char* sep = 0,
|
||||
int maxsplit = 0 );
|
||||
|
||||
} // end namespace strutils
|
||||
|
||||
} // end namespace strutils
|
||||
} // end namespace simgear
|
||||
|
||||
#endif // STRUTILS_H
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
// $Id$
|
||||
|
||||
#include <cstdlib>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tabbed_values.hxx"
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
SGTabbedValues::SGTabbedValues(const char *line) :
|
||||
_line(line)
|
||||
|
||||
@@ -149,6 +149,7 @@ enter this in the official comments in case I forget again. :-)
|
||||
|
||||
#include "texcoord.hxx"
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
// using std::cout;
|
||||
// using std::endl;
|
||||
|
||||
|
||||
@@ -20,10 +20,6 @@ void printOpDEBUG(int ip, int op);
|
||||
void printStackDEBUG(naContext ctx);
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
struct Globals* globals = 0;
|
||||
|
||||
static naRef bindFunction(naContext ctx, struct Frame* f, naRef code);
|
||||
|
||||
+40
-2
@@ -67,6 +67,15 @@ static naRef f_tell(naContext c, naRef me, int argc, naRef* args)
|
||||
return naNum(g->type->tell(c, g->handle));
|
||||
}
|
||||
|
||||
static naRef f_flush(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
struct naIOGhost* g = argc==1 ? ioghost(args[0]) : 0;
|
||||
if(!g)
|
||||
naRuntimeError(c, "bad argument to flush()");
|
||||
g->type->flush(c, g->handle);
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static void ghostDestroy(void* g)
|
||||
{
|
||||
struct naIOGhost* io = (struct naIOGhost*)g;
|
||||
@@ -111,6 +120,11 @@ static int iotell(naContext c, void* f)
|
||||
return n;
|
||||
}
|
||||
|
||||
static void ioflush(naContext c, void* f)
|
||||
{
|
||||
if(fflush(f)) naRuntimeError(c, strerror(errno));
|
||||
}
|
||||
|
||||
static void iodestroy(void* f)
|
||||
{
|
||||
if(f != stdin && f != stdout && f != stderr)
|
||||
@@ -118,7 +132,7 @@ static void iodestroy(void* f)
|
||||
}
|
||||
|
||||
struct naIOType naStdIOType = { ioclose, ioread, iowrite, ioseek,
|
||||
iotell, iodestroy };
|
||||
iotell, ioflush, iodestroy };
|
||||
|
||||
naRef naIOGhost(naContext c, FILE* f)
|
||||
{
|
||||
@@ -181,6 +195,28 @@ static naRef f_readln(naContext ctx, naRef me, int argc, naRef* args)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define S_ISLNK(m) 0
|
||||
#define S_ISSOCK(m) 0
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#define S_ISREG(m) (((m)&_S_IFMT)==_S_IFREG)
|
||||
#define S_ISDIR(m) (((m)&_S_IFMT)==_S_IFDIR)
|
||||
#define S_ISCHR(m) (((m)&_S_IFMT)==_S_IFCHR)
|
||||
#define S_ISFIFO(m) (((m)&_S_IFMT)==_S_IFIFO)
|
||||
#define S_ISBLK(m) 0
|
||||
typedef unsigned short mode_t;
|
||||
#endif
|
||||
static naRef ftype(naContext ctx, mode_t m)
|
||||
{
|
||||
const char* t = "unk";
|
||||
if(S_ISREG(m)) t = "reg";
|
||||
else if(S_ISDIR(m)) t = "dir"; else if(S_ISCHR(m)) t = "chr";
|
||||
else if(S_ISBLK(m)) t = "blk"; else if(S_ISFIFO(m)) t = "fifo";
|
||||
else if(S_ISLNK(m)) t = "lnk"; else if(S_ISSOCK(m)) t = "sock";
|
||||
return naStr_fromdata(naNewString(ctx), t, strlen(t));
|
||||
}
|
||||
|
||||
static naRef f_stat(naContext ctx, naRef me, int argc, naRef* args)
|
||||
{
|
||||
int n=0;
|
||||
@@ -192,11 +228,12 @@ static naRef f_stat(naContext ctx, naRef me, int argc, naRef* args)
|
||||
naRuntimeError(ctx, strerror(errno));
|
||||
}
|
||||
result = naNewVector(ctx);
|
||||
naVec_setsize(result, 11);
|
||||
naVec_setsize(result, 12);
|
||||
#define FLD(x) naVec_set(result, n++, naNum(s.st_##x));
|
||||
FLD(dev); FLD(ino); FLD(mode); FLD(nlink); FLD(uid); FLD(gid);
|
||||
FLD(rdev); FLD(size); FLD(atime); FLD(mtime); FLD(ctime);
|
||||
#undef FLD
|
||||
naVec_set(result, n++, ftype(ctx, s.st_mode));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -206,6 +243,7 @@ static naCFuncItem funcs[] = {
|
||||
{ "write", f_write },
|
||||
{ "seek", f_seek },
|
||||
{ "tell", f_tell },
|
||||
{ "flush", f_flush },
|
||||
{ "open", f_open },
|
||||
{ "readln", f_readln },
|
||||
{ "stat", f_stat },
|
||||
|
||||
@@ -15,6 +15,7 @@ struct naIOType {
|
||||
int (*write)(naContext c, void* f, char* buf, unsigned int len);
|
||||
void (*seek) (naContext c, void* f, unsigned int off, int whence);
|
||||
int (*tell) (naContext c, void* f);
|
||||
void (*flush) (naContext c, void* f);
|
||||
void (*destroy)(void* f);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
* tested */
|
||||
# define NASAL_NAN64
|
||||
#elif defined(_M_IX86) || defined(i386) || defined(__x86_64) || \
|
||||
defined(__ia64__) || defined(_M_IA64) || defined(__ARMEL__)
|
||||
defined(__ia64__) || defined(_M_IA64) || defined(__ARMEL__) || \
|
||||
defined(_M_X64)
|
||||
# define NASAL_LE
|
||||
#elif defined(__sparc) || defined(__ppc__) || defined(__PPC) || \
|
||||
defined(__mips) || defined(__ARMEB__)
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include "AtomicChangeListener.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
MultiChangeListener::MultiChangeListener()
|
||||
{
|
||||
}
|
||||
|
||||
void MultiChangeListener::valueChanged(SGPropertyNode* node)
|
||||
{
|
||||
valueChangedImplementation();
|
||||
}
|
||||
|
||||
void MultiChangeListener::valueChangedImplementation()
|
||||
{
|
||||
}
|
||||
|
||||
AtomicChangeListener::AtomicChangeListener(std::vector<SGPropertyNode*>& nodes)
|
||||
: _dirty(false), _valid(true)
|
||||
{
|
||||
listenToProperties(nodes.begin(), nodes.end());
|
||||
}
|
||||
|
||||
void AtomicChangeListener::unregister_property(SGPropertyNode* node)
|
||||
{
|
||||
_valid = false;
|
||||
// not necessary, but good hygine
|
||||
vector<SGPropertyNode*>::iterator itr
|
||||
= find(_watched.begin(), _watched.end(), node);
|
||||
if (itr != _watched.end())
|
||||
*itr = 0;
|
||||
MultiChangeListener::unregister_property(node);
|
||||
}
|
||||
|
||||
void AtomicChangeListener::fireChangeListeners()
|
||||
{
|
||||
vector<SGSharedPtr<AtomicChangeListener> >& listeners
|
||||
= ListenerListSingleton::instance()->listeners;
|
||||
for (vector<SGSharedPtr<AtomicChangeListener> >::iterator itr = listeners.begin(),
|
||||
end = listeners.end();
|
||||
itr != end;
|
||||
++itr) {
|
||||
(*itr)->valuesChanged();
|
||||
(*itr)->_dirty = false;
|
||||
}
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
void AtomicChangeListener::valueChangedImplementation()
|
||||
{
|
||||
if (!_dirty) {
|
||||
_dirty = true;
|
||||
if (_valid)
|
||||
ListenerListSingleton::instance()->listeners.push_back(this);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomicChangeListener::valuesChanged()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
#ifndef SIMGEAR_ATOMICCHANGELISTENER_HXX
|
||||
#define SIMGEAR_ATOMICCHANGELISTENER_HXX 1
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
#include "ExtendedPropertyAdapter.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
// Performs an action when one of several nodes changes
|
||||
class MultiChangeListener : public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
MultiChangeListener();
|
||||
template<typename Pitr>
|
||||
void listenToProperties(Pitr propsBegin, Pitr propsEnd)
|
||||
{
|
||||
for (Pitr itr = propsBegin, end = propsEnd; itr != end; ++itr)
|
||||
(*itr)->addChangeListener(this);
|
||||
}
|
||||
private:
|
||||
void valueChanged(SGPropertyNode* node);
|
||||
virtual void valueChangedImplementation();
|
||||
|
||||
};
|
||||
|
||||
class AtomicChangeListener : public MultiChangeListener,
|
||||
public virtual SGReferenced
|
||||
{
|
||||
public:
|
||||
AtomicChangeListener(std::vector<SGPropertyNode*>& nodes);
|
||||
/**
|
||||
* Lookup / create child nodes from their relative names.
|
||||
*/
|
||||
template<typename Itr>
|
||||
AtomicChangeListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||
Itr childNamesEnd)
|
||||
: _dirty(false), _valid(true)
|
||||
{
|
||||
using namespace std;
|
||||
for (Itr itr = childNamesBegin, end = childNamesEnd;
|
||||
itr != end;
|
||||
++itr)
|
||||
_watched.push_back(makeNode(parent, *itr));
|
||||
listenToProperties(_watched.begin(), _watched.end());
|
||||
}
|
||||
bool isDirty() { return _dirty; }
|
||||
bool isValid() { return _valid; }
|
||||
void unregister_property(SGPropertyNode* node);
|
||||
static void fireChangeListeners();
|
||||
private:
|
||||
virtual void valueChangedImplementation();
|
||||
virtual void valuesChanged();
|
||||
bool _dirty;
|
||||
bool _valid;
|
||||
struct ListenerListSingleton : public Singleton<ListenerListSingleton>
|
||||
{
|
||||
std::vector<SGSharedPtr<AtomicChangeListener> > listeners;
|
||||
};
|
||||
protected:
|
||||
std::vector<SGPropertyNode*> _watched;
|
||||
};
|
||||
|
||||
template<typename T, typename Func>
|
||||
class ExtendedPropListener : public AtomicChangeListener
|
||||
{
|
||||
public:
|
||||
ExtendedPropListener(std::vector<SGPropertyNode*>& nodes, const Func& func,
|
||||
bool initial = false)
|
||||
: AtomicChangeListener(nodes), _func(func)
|
||||
{
|
||||
if (initial)
|
||||
valuesChanged();
|
||||
|
||||
}
|
||||
template<typename Itr>
|
||||
ExtendedPropListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||
Itr childNamesEnd, const Func& func,
|
||||
bool initial = false)
|
||||
: AtomicChangeListener(parent, childNamesBegin, childNamesEnd),
|
||||
_func(func)
|
||||
{
|
||||
if (initial)
|
||||
valuesChanged();
|
||||
}
|
||||
virtual void valuesChanged()
|
||||
{
|
||||
ExtendedPropertyAdapter<T, std::vector<SGPropertyNode*> > adaptor(_watched);
|
||||
T val = adaptor();
|
||||
_func(val);
|
||||
}
|
||||
private:
|
||||
Func _func;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX
|
||||
#define SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX 1
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
namespace props
|
||||
{
|
||||
// This should be in simgear/math/SGVec.hxx and friends
|
||||
|
||||
template<typename T> struct NumComponents;
|
||||
|
||||
template<> struct NumComponents<SGVec3d>
|
||||
{
|
||||
enum { num_components = 3 };
|
||||
};
|
||||
|
||||
template<> struct NumComponents<SGVec4d>
|
||||
{
|
||||
enum { num_components = 4 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename NodeContainer>
|
||||
class ExtendedPropertyAdapter
|
||||
{
|
||||
public:
|
||||
enum { num_components = props::NumComponents<T>::num_components };
|
||||
ExtendedPropertyAdapter(const NodeContainer& elements)
|
||||
: _elements(elements)
|
||||
{
|
||||
}
|
||||
T operator()() const
|
||||
{
|
||||
T result;
|
||||
if (_elements.size() < num_components)
|
||||
throw sg_exception();
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
result[i] = _elements[i]->getValue<double>();
|
||||
return result;
|
||||
}
|
||||
void set(const T& val)
|
||||
{
|
||||
if (_elements.size() < num_components)
|
||||
throw sg_exception();
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
_elements[i]->setValue(val[i]);
|
||||
}
|
||||
private:
|
||||
const NodeContainer& _elements;
|
||||
};
|
||||
|
||||
template<typename InIterator, typename OutIterator>
|
||||
inline void makeChildList(SGPropertyNode* prop, InIterator inBegin,
|
||||
InIterator inEnd, OutIterator outBegin)
|
||||
{
|
||||
std::transform(inBegin, inEnd, outBegin,
|
||||
boost::bind(static_cast<SGPropertyNode* (SGPropertyNode::*)(const char*, int, bool)>(&SGPropertyNode::getChild), prop, _1, 0, true));
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -5,14 +5,17 @@ lib_LIBRARIES = libsgprops.a
|
||||
include_HEADERS = \
|
||||
condition.hxx \
|
||||
props.hxx \
|
||||
props_io.hxx
|
||||
props_io.hxx \
|
||||
AtomicChangeListener.hxx \
|
||||
ExtendedPropertyAdapter.hxx
|
||||
|
||||
libsgprops_a_SOURCES = \
|
||||
condition.cxx \
|
||||
props.cxx \
|
||||
props_io.cxx
|
||||
props_io.cxx \
|
||||
AtomicChangeListener.cxx
|
||||
|
||||
noinst_PROGRAMS = props_test
|
||||
check_PROGRAMS = props_test
|
||||
|
||||
props_test_SOURCES = props_test.cxx
|
||||
props_test_LDADD = \
|
||||
@@ -22,4 +25,10 @@ props_test_LDADD = \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/structure/libsgstructure.a
|
||||
|
||||
if HAVE_FRAMEWORK_OSG
|
||||
props_test_LDFLAGS = $(openthreads_FRAMEWORK)
|
||||
else
|
||||
props_test_LDFLAGS = -lOpenThreads
|
||||
endif
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
||||
+15
-10
@@ -8,7 +8,7 @@
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear/compiler.h>
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
// #include <iostream>
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "props.hxx"
|
||||
#include "condition.hxx"
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
|
||||
@@ -144,8 +146,9 @@ SGOrCondition::addCondition (SGCondition * condition)
|
||||
static int
|
||||
doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
{
|
||||
using namespace simgear;
|
||||
switch (left->getType()) {
|
||||
case SGPropertyNode::BOOL: {
|
||||
case props::BOOL: {
|
||||
bool v1 = left->getBoolValue();
|
||||
bool v2 = right->getBoolValue();
|
||||
if (v1 < v2)
|
||||
@@ -156,7 +159,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::INT: {
|
||||
case props::INT: {
|
||||
int v1 = left->getIntValue();
|
||||
int v2 = right->getIntValue();
|
||||
if (v1 < v2)
|
||||
@@ -167,7 +170,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::LONG: {
|
||||
case props::LONG: {
|
||||
long v1 = left->getLongValue();
|
||||
long v2 = right->getLongValue();
|
||||
if (v1 < v2)
|
||||
@@ -178,7 +181,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::FLOAT: {
|
||||
case props::FLOAT: {
|
||||
float v1 = left->getFloatValue();
|
||||
float v2 = right->getFloatValue();
|
||||
if (v1 < v2)
|
||||
@@ -189,7 +192,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::DOUBLE: {
|
||||
case props::DOUBLE: {
|
||||
double v1 = left->getDoubleValue();
|
||||
double v2 = right->getDoubleValue();
|
||||
if (v1 < v2)
|
||||
@@ -200,9 +203,9 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::STRING:
|
||||
case SGPropertyNode::NONE:
|
||||
case SGPropertyNode::UNSPECIFIED: {
|
||||
case props::STRING:
|
||||
case props::NONE:
|
||||
case props::UNSPECIFIED: {
|
||||
string v1 = left->getStringValue();
|
||||
string v2 = right->getStringValue();
|
||||
if (v1 < v2)
|
||||
@@ -213,8 +216,10 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw sg_exception("condition: unrecognized node type in comparison");
|
||||
}
|
||||
throw sg_exception("condition: unrecognized node type in comparison");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+841
-676
File diff suppressed because it is too large
Load Diff
+555
-128
@@ -18,6 +18,10 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#if PROPS_STANDALONE
|
||||
#else
|
||||
@@ -26,10 +30,49 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <simgear/math/SGMathFwd.hxx>
|
||||
#include <simgear/structure/SGReferenced.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
|
||||
// XXX This whole file should be in the simgear namespace, but I don't
|
||||
// have the guts yet...
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
template<typename T>
|
||||
std::istream& readFrom(std::istream& stream, T& result)
|
||||
{
|
||||
stream >> result;
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a string as an object of a given type.
|
||||
* XXX no error behavior yet.
|
||||
*
|
||||
* @tparam T the return type
|
||||
* @param str the string
|
||||
* @return the object.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T parseString(const std::string& str)
|
||||
{
|
||||
std::istringstream stream(str);
|
||||
T result;
|
||||
readFrom(stream, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Extended properties
|
||||
template<>
|
||||
std::istream& readFrom<SGVec3d>(std::istream& stream, SGVec3d& result);
|
||||
template<>
|
||||
std::istream& readFrom<SGVec4d>(std::istream& stream, SGVec4d& result);
|
||||
|
||||
|
||||
/**
|
||||
* Property value types.
|
||||
*/
|
||||
|
||||
#ifdef NONE
|
||||
#pragma warn A sloppy coder has defined NONE as a macro!
|
||||
@@ -76,6 +119,68 @@
|
||||
#undef STRING
|
||||
#endif
|
||||
|
||||
namespace props
|
||||
{
|
||||
/**
|
||||
* The possible types of an SGPropertyNode. Types that appear after
|
||||
* EXTENDED are not stored in the SGPropertyNode itself.
|
||||
*/
|
||||
enum Type {
|
||||
NONE = 0, /**< The node hasn't been assigned a value yet. */
|
||||
ALIAS, /**< The node "points" to another node. */
|
||||
BOOL,
|
||||
INT,
|
||||
LONG,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
STRING,
|
||||
UNSPECIFIED,
|
||||
EXTENDED, /**< The node's value is not stored in the property;
|
||||
* the actual value and type is retrieved from an
|
||||
* SGRawValue node. This type is never returned by @see
|
||||
* SGPropertyNode::getType.
|
||||
*/
|
||||
// Extended properties
|
||||
VEC3D,
|
||||
VEC4D
|
||||
};
|
||||
|
||||
template<typename T> struct PropertyTraits;
|
||||
|
||||
#define DEFINTERNALPROP(TYPE, PROP) \
|
||||
template<> \
|
||||
struct PropertyTraits<TYPE> \
|
||||
{ \
|
||||
static const Type type_tag = PROP; \
|
||||
enum { Internal = 1 }; \
|
||||
}
|
||||
|
||||
DEFINTERNALPROP(bool, BOOL);
|
||||
DEFINTERNALPROP(int, INT);
|
||||
DEFINTERNALPROP(long, LONG);
|
||||
DEFINTERNALPROP(float, FLOAT);
|
||||
DEFINTERNALPROP(double, DOUBLE);
|
||||
DEFINTERNALPROP(const char *, STRING);
|
||||
DEFINTERNALPROP(const char[], STRING);
|
||||
#undef DEFINTERNALPROP
|
||||
|
||||
template<>
|
||||
struct PropertyTraits<SGVec3d>
|
||||
{
|
||||
static const Type type_tag = VEC3D;
|
||||
enum { Internal = 0 };
|
||||
};
|
||||
|
||||
template<>
|
||||
struct PropertyTraits<SGVec4d>
|
||||
{
|
||||
static const Type type_tag = VEC4D;
|
||||
enum { Internal = 0 };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -90,6 +195,74 @@
|
||||
// a small performance hit for that.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Base class for SGRawValue classes that holds no type
|
||||
* information. This allows some generic manipulation of the
|
||||
* SGRawValue object.
|
||||
*/
|
||||
class SGRaw
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get the type enumeration for the raw value.
|
||||
*
|
||||
* @return the type.
|
||||
*/
|
||||
virtual simgear::props::Type getType() const = 0;
|
||||
virtual ~SGRaw() {}
|
||||
|
||||
/**
|
||||
* Create a new deep copy of this raw value.
|
||||
*
|
||||
* The copy will contain its own version of the underlying value
|
||||
* as well, and will be the same type.
|
||||
*
|
||||
* @return A deep copy of the current object.
|
||||
*/
|
||||
virtual SGRaw* clone() const = 0;
|
||||
|
||||
};
|
||||
|
||||
class SGRawExtended : public SGRaw
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Make an SGRawValueContainer from the SGRawValue.
|
||||
*
|
||||
* This is a virtual function of SGRawExtended so that
|
||||
* SGPropertyNode::untie doesn't need to know the type of an
|
||||
* extended property.
|
||||
*/
|
||||
virtual SGRawExtended* makeContainer() const = 0;
|
||||
/**
|
||||
* Write value out to a stream
|
||||
*/
|
||||
virtual std::ostream& printOn(std::ostream& stream) const = 0;
|
||||
/**
|
||||
* Read value from a stream and store it.
|
||||
*/
|
||||
virtual std::istream& readFrom(std::istream& stream) = 0;
|
||||
};
|
||||
|
||||
// Choose between different base classes based on whether the value is
|
||||
// stored internal to the property node. This frees us from defining
|
||||
// the virtual functions in the SGRawExtended interface where they
|
||||
// don't make sense, e.g. readFrom for the const char* type.
|
||||
template<typename T, int internal = simgear::props::PropertyTraits<T>::Internal>
|
||||
class SGRawBase;
|
||||
|
||||
template<typename T>
|
||||
class SGRawBase<T, 1> : public SGRaw
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class SGRawBase<T, 0> : public SGRawExtended
|
||||
{
|
||||
virtual SGRawExtended* makeContainer() const;
|
||||
virtual std::ostream& printOn(std::ostream& stream) const;
|
||||
virtual std::istream& readFrom(std::istream& stream);
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract base class for a raw value.
|
||||
@@ -108,10 +281,7 @@
|
||||
* set, and clone the underlying value. The SGRawValue may change
|
||||
* frequently during a session as a value is retyped or bound and
|
||||
* unbound to various data source, but the abstract SGPropertyNode
|
||||
* layer insulates the application from those changes. The raw value
|
||||
* contains no facilities for data binding or for type conversion: it
|
||||
* is simply the abstraction of a primitive data type (or a compound
|
||||
* data type, in the case of a string).</p>
|
||||
* layer insulates the application from those changes.
|
||||
*
|
||||
* <p>The SGPropertyNode class always keeps a *copy* of a raw value,
|
||||
* not the original one passed to it; if you override a derived class
|
||||
@@ -127,9 +297,10 @@
|
||||
* @see SGRawValueFunctionsIndexed
|
||||
* @see SGRawValueMethods
|
||||
* @see SGRawValueMethodsIndexed
|
||||
* @see SGRawValueContainer
|
||||
*/
|
||||
template <class T>
|
||||
class SGRawValue
|
||||
class SGRawValue : public SGRawBase<T>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -142,7 +313,10 @@ public:
|
||||
* may need different kinds of default values (such as epoch for a
|
||||
* date type). The default value is used when creating new values.
|
||||
*/
|
||||
static const T DefaultValue; // Default for this kind of raw value.
|
||||
static T DefaultValue()
|
||||
{
|
||||
return T();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -184,17 +358,30 @@ public:
|
||||
|
||||
|
||||
/**
|
||||
* Create a new deep copy of this raw value.
|
||||
*
|
||||
* The copy will contain its own version of the underlying value
|
||||
* as well.
|
||||
*
|
||||
* @return A deep copy of the current object.
|
||||
* Return the type tag for this raw value type.
|
||||
*/
|
||||
virtual SGRawValue * clone () const = 0;
|
||||
virtual simgear::props::Type getType() const
|
||||
{
|
||||
return simgear::props::PropertyTraits<T>::type_tag;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Default values for every type.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<> inline bool SGRawValue<bool>::DefaultValue()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<> inline const char * SGRawValue<const char *>::DefaultValue()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* A raw value bound to a pointer.
|
||||
*
|
||||
@@ -247,8 +434,8 @@ public:
|
||||
*
|
||||
* The copy will use the same external pointer as the original.
|
||||
*/
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValuePointer<T>(_ptr);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValuePointer(_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -304,7 +491,7 @@ public:
|
||||
*/
|
||||
virtual T getValue () const {
|
||||
if (_getter) return (*_getter)();
|
||||
else return SGRawValue<T>::DefaultValue;
|
||||
else return SGRawValue<T>::DefaultValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,8 +509,8 @@ public:
|
||||
/**
|
||||
* Create a copy of this raw value, bound to the same functions.
|
||||
*/
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueFunctions<T>(_getter,_setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueFunctions(_getter,_setter);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -353,14 +540,14 @@ public:
|
||||
virtual ~SGRawValueFunctionsIndexed () {}
|
||||
virtual T getValue () const {
|
||||
if (_getter) return (*_getter)(_index);
|
||||
else return SGRawValue<T>::DefaultValue;
|
||||
else return SGRawValue<T>::DefaultValue();
|
||||
}
|
||||
virtual bool setValue (T value) {
|
||||
if (_setter) { (*_setter)(_index, value); return true; }
|
||||
else return false;
|
||||
}
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueFunctionsIndexed<T>(_index, _getter, _setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueFunctionsIndexed(_index, _getter, _setter);
|
||||
}
|
||||
private:
|
||||
int _index;
|
||||
@@ -386,14 +573,14 @@ public:
|
||||
virtual ~SGRawValueMethods () {}
|
||||
virtual T getValue () const {
|
||||
if (_getter) { return (_obj.*_getter)(); }
|
||||
else { return SGRawValue<T>::DefaultValue; }
|
||||
else { return SGRawValue<T>::DefaultValue(); }
|
||||
}
|
||||
virtual bool setValue (T value) {
|
||||
if (_setter) { (_obj.*_setter)(value); return true; }
|
||||
else return false;
|
||||
}
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueMethods<C,T>(_obj, _getter, _setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueMethods(_obj, _getter, _setter);
|
||||
}
|
||||
private:
|
||||
C &_obj;
|
||||
@@ -420,14 +607,14 @@ public:
|
||||
virtual ~SGRawValueMethodsIndexed () {}
|
||||
virtual T getValue () const {
|
||||
if (_getter) { return (_obj.*_getter)(_index); }
|
||||
else { return SGRawValue<T>::DefaultValue; }
|
||||
else { return SGRawValue<T>::DefaultValue(); }
|
||||
}
|
||||
virtual bool setValue (T value) {
|
||||
if (_setter) { (_obj.*_setter)(_index, value); return true; }
|
||||
else return false;
|
||||
}
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueMethodsIndexed<C,T>(_obj, _index, _getter, _setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueMethodsIndexed(_obj, _index, _getter, _setter);
|
||||
}
|
||||
private:
|
||||
C &_obj;
|
||||
@@ -436,6 +623,77 @@ private:
|
||||
setter_t _setter;
|
||||
};
|
||||
|
||||
/**
|
||||
* A raw value that contains its value. This provides a way for
|
||||
* property nodes to contain values that shouldn't be stored in the
|
||||
* property node itself.
|
||||
*/
|
||||
template <class T>
|
||||
class SGRawValueContainer : public SGRawValue<T>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Explicit constructor.
|
||||
*/
|
||||
SGRawValueContainer(const T& obj) : _obj(obj) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~SGRawValueContainer() {}
|
||||
|
||||
/**
|
||||
* Get the underlying value.
|
||||
*/
|
||||
virtual T getValue() const { return _obj; }
|
||||
|
||||
/**
|
||||
* Set the underlying value.
|
||||
*
|
||||
* This method will dereference the pointer and change the
|
||||
* variable's value.
|
||||
*/
|
||||
virtual bool setValue (T value) { _obj = value; return true; }
|
||||
|
||||
/**
|
||||
* Create a copy of this raw value.
|
||||
*/
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueContainer(_obj);
|
||||
}
|
||||
|
||||
private:
|
||||
T _obj;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
SGRawExtended* SGRawBase<T, 0>::makeContainer() const
|
||||
{
|
||||
return new SGRawValueContainer<T>(static_cast<const SGRawValue<T>*>(this)
|
||||
->getValue());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& SGRawBase<T, 0>::printOn(std::ostream& stream) const
|
||||
{
|
||||
return stream << static_cast<SGRawValue<T>*>(this)->getValue();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::istream& SGRawBase<T, 0>::readFrom(std::istream& stream)
|
||||
{
|
||||
T value;
|
||||
simgear::readFrom(stream, value);
|
||||
static_cast<SGRawValue<T>*>(this)->setValue(value);
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::ostream& SGRawBase<SGVec3d>::printOn(std::ostream& stream) const;
|
||||
template<>
|
||||
std::ostream& SGRawBase<SGVec4d>::printOn(std::ostream& stream) const;
|
||||
|
||||
|
||||
/**
|
||||
* The smart pointer that manage reference counting
|
||||
@@ -444,6 +702,11 @@ class SGPropertyNode;
|
||||
typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
|
||||
typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
typedef std::vector<SGPropertyNode_ptr> PropertyList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The property change listener interface.
|
||||
@@ -484,22 +747,6 @@ public:
|
||||
MAX_STRING_LEN = 1024
|
||||
};
|
||||
|
||||
/**
|
||||
* Property value types.
|
||||
*/
|
||||
enum Type {
|
||||
NONE = 0,
|
||||
ALIAS,
|
||||
BOOL,
|
||||
INT,
|
||||
LONG,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
STRING,
|
||||
UNSPECIFIED
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Access mode attributes.
|
||||
*
|
||||
@@ -550,7 +797,7 @@ public:
|
||||
/**
|
||||
* Test whether this node contains a primitive leaf value.
|
||||
*/
|
||||
bool hasValue () const { return (_type != NONE); }
|
||||
bool hasValue () const { return (_type != simgear::props::NONE); }
|
||||
|
||||
|
||||
/**
|
||||
@@ -558,11 +805,15 @@ public:
|
||||
*/
|
||||
const char * getName () const { return _name.c_str(); }
|
||||
|
||||
/**
|
||||
* Get the node's simple name as a string.
|
||||
*/
|
||||
const std::string& getNameString () const { return _name; }
|
||||
|
||||
/**
|
||||
* Get the node's pretty display name, with subscript when needed.
|
||||
*/
|
||||
const char * getDisplayName (bool simplify = false) const;
|
||||
std::string getDisplayName (bool simplify = false) const;
|
||||
|
||||
|
||||
/**
|
||||
@@ -591,7 +842,7 @@ public:
|
||||
/**
|
||||
* Get the number of child nodes.
|
||||
*/
|
||||
int nChildren () const { return _children.size(); }
|
||||
int nChildren () const { return (int)_children.size(); }
|
||||
|
||||
|
||||
/**
|
||||
@@ -622,21 +873,18 @@ public:
|
||||
return (getChild(name, index) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a child node after the last node with the same name.
|
||||
*/
|
||||
SGPropertyNode * addChild (const char * name);
|
||||
|
||||
/**
|
||||
* Get a child node by name and index.
|
||||
*/
|
||||
SGPropertyNode * getChild (const char * name, int index = 0,
|
||||
bool create = false);
|
||||
|
||||
/**
|
||||
* Get a child node by name and index.
|
||||
*/
|
||||
SGPropertyNode * getChild (const char* name, int index = 0,
|
||||
bool create = false);
|
||||
SGPropertyNode * getChild (const std::string& name, int index = 0,
|
||||
bool create = false)
|
||||
{ return getChild(name.c_str(), index, create); }
|
||||
|
||||
|
||||
bool create = false);
|
||||
/**
|
||||
* Get a const child node by name and index.
|
||||
*/
|
||||
@@ -652,12 +900,12 @@ public:
|
||||
/**
|
||||
* Get a vector of all children with the specified name.
|
||||
*/
|
||||
std::vector<SGPropertyNode_ptr> getChildren (const char * name) const;
|
||||
simgear::PropertyList getChildren (const char * name) const;
|
||||
|
||||
/**
|
||||
* Get a vector of all children with the specified name.
|
||||
*/
|
||||
std::vector<SGPropertyNode_ptr> getChildren (const std::string& name) const
|
||||
simgear::PropertyList getChildren (const std::string& name) const
|
||||
{ return getChildren(name.c_str()); }
|
||||
|
||||
/**
|
||||
@@ -682,15 +930,13 @@ public:
|
||||
/**
|
||||
* Remove all children with the specified name.
|
||||
*/
|
||||
std::vector<SGPropertyNode_ptr> removeChildren (const char * name,
|
||||
bool keep = true);
|
||||
|
||||
simgear::PropertyList removeChildren (const char * name, bool keep = true);
|
||||
|
||||
/**
|
||||
* Remove all children with the specified name.
|
||||
*/
|
||||
std::vector<SGPropertyNode_ptr> removeChildren (const std::string& name,
|
||||
bool keep = true)
|
||||
simgear::PropertyList removeChildren (const std::string& name,
|
||||
bool keep = true)
|
||||
{ return removeChildren(name.c_str(), keep); }
|
||||
|
||||
//
|
||||
@@ -725,7 +971,7 @@ public:
|
||||
/**
|
||||
* Test whether the node's leaf value is aliased to another's.
|
||||
*/
|
||||
bool isAlias () const { return (_type == ALIAS); }
|
||||
bool isAlias () const { return (_type == simgear::props::ALIAS); }
|
||||
|
||||
|
||||
/**
|
||||
@@ -748,7 +994,7 @@ public:
|
||||
/**
|
||||
* Get the path to this node from the root.
|
||||
*/
|
||||
const char * getPath (bool simplify = false) const;
|
||||
std::string getPath (bool simplify = false) const;
|
||||
|
||||
|
||||
/**
|
||||
@@ -870,7 +1116,7 @@ public:
|
||||
/**
|
||||
* Get the type of leaf value, if any, for this node.
|
||||
*/
|
||||
Type getType () const;
|
||||
simgear::props::Type getType () const;
|
||||
|
||||
|
||||
/**
|
||||
@@ -908,7 +1154,17 @@ public:
|
||||
*/
|
||||
const char * getStringValue () const;
|
||||
|
||||
|
||||
/**
|
||||
* Get a value from a node. If the actual type of the node doesn't
|
||||
* match the desired type, a conversion isn't guaranteed.
|
||||
*/
|
||||
template<typename T>
|
||||
T getValue(typename boost::enable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0) const;
|
||||
// Getter for extended property
|
||||
template<typename T>
|
||||
T getValue(typename boost::disable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0) const;
|
||||
|
||||
/**
|
||||
* Set a bool value for this node.
|
||||
@@ -957,7 +1213,27 @@ public:
|
||||
*/
|
||||
bool setUnspecifiedValue (const char * value);
|
||||
|
||||
template<typename T>
|
||||
bool setValue(const T& val,
|
||||
typename boost::enable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0);
|
||||
|
||||
template<typename T>
|
||||
bool setValue(const T& val,
|
||||
typename boost::disable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0);
|
||||
|
||||
template<int N>
|
||||
bool setValue(const char (&val)[N])
|
||||
{
|
||||
return setValue(&val[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the value of the property to a stream.
|
||||
*/
|
||||
std::ostream& printOn(std::ostream& stream) const;
|
||||
|
||||
//
|
||||
// Data binding.
|
||||
//
|
||||
@@ -968,42 +1244,11 @@ public:
|
||||
*/
|
||||
bool isTied () const { return _tied; }
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external bool source.
|
||||
*/
|
||||
bool tie (const SGRawValue<bool> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external int source.
|
||||
*/
|
||||
bool tie (const SGRawValue<int> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external long int source.
|
||||
*/
|
||||
bool tie (const SGRawValue<long> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external float source.
|
||||
*/
|
||||
bool tie (const SGRawValue<float> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external double source.
|
||||
*/
|
||||
bool tie (const SGRawValue<double> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external string source.
|
||||
*/
|
||||
bool tie (const SGRawValue<const char *> &rawValue, bool useDefault = true);
|
||||
|
||||
/**
|
||||
* Bind this node to an external source.
|
||||
*/
|
||||
template<typename T>
|
||||
bool tie(const SGRawValue<T> &rawValue, bool useDefault = true);
|
||||
|
||||
/**
|
||||
* Unbind this node from any external data source.
|
||||
@@ -1020,12 +1265,12 @@ public:
|
||||
/**
|
||||
* Get another node's type.
|
||||
*/
|
||||
Type getType (const char * relative_path) const;
|
||||
simgear::props::Type getType (const char * relative_path) const;
|
||||
|
||||
/**
|
||||
* Get another node's type.
|
||||
*/
|
||||
Type getType (const std::string& relative_path) const
|
||||
simgear::props::Type getType (const std::string& relative_path) const
|
||||
{ return getType(relative_path.c_str()); }
|
||||
|
||||
/**
|
||||
@@ -1186,12 +1431,17 @@ public:
|
||||
*/
|
||||
bool setStringValue (const char * relative_path, const char * value);
|
||||
|
||||
bool setStringValue(const char * relative_path, const std::string& value)
|
||||
{ return setStringValue(relative_path, value.c_str()); }
|
||||
/**
|
||||
* Set another node's value as a string.
|
||||
*/
|
||||
bool setStringValue (const std::string& relative_path, const char * value)
|
||||
{ return setStringValue(relative_path.c_str(), value); }
|
||||
|
||||
bool setStringValue (const std::string& relative_path,
|
||||
const std::string& value)
|
||||
{ return setStringValue(relative_path.c_str(), value.c_str()); }
|
||||
|
||||
/**
|
||||
* Set another node's value with no specified type.
|
||||
@@ -1323,7 +1573,7 @@ public:
|
||||
/**
|
||||
* Get the number of listeners.
|
||||
*/
|
||||
int nListeners () const { return _listeners ? _listeners->size() : 0; }
|
||||
int nListeners () const { return _listeners ? (int)_listeners->size() : 0; }
|
||||
|
||||
|
||||
/**
|
||||
@@ -1349,6 +1599,16 @@ public:
|
||||
*/
|
||||
void clearValue ();
|
||||
|
||||
/**
|
||||
* Compare two property trees. The property trees are equal if: 1)
|
||||
* They have no children, and have the same type and the values are
|
||||
* equal, or 2) have the same number of children, and the
|
||||
* corresponding children in each tree are equal. "corresponding"
|
||||
* means have the same name and index.
|
||||
*
|
||||
* Attributes, removed children, and aliases aren't considered.
|
||||
*/
|
||||
static bool compare (const SGPropertyNode& lhs, const SGPropertyNode& rhs);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1359,12 +1619,13 @@ protected:
|
||||
/**
|
||||
* Protected constructor for making new nodes on demand.
|
||||
*/
|
||||
SGPropertyNode (const char * name, int index, SGPropertyNode * parent);
|
||||
|
||||
SGPropertyNode (const std::string& name, int index, SGPropertyNode * parent);
|
||||
template<typename Itr>
|
||||
SGPropertyNode (Itr begin, Itr end, int index, SGPropertyNode * parent);
|
||||
|
||||
private:
|
||||
|
||||
// Get the raw value
|
||||
// Get the raw value
|
||||
bool get_bool () const;
|
||||
int get_int () const;
|
||||
long get_long () const;
|
||||
@@ -1372,7 +1633,7 @@ private:
|
||||
double get_double () const;
|
||||
const char * get_string () const;
|
||||
|
||||
// Set the raw value
|
||||
// Set the raw value
|
||||
bool set_bool (bool value);
|
||||
bool set_int (int value);
|
||||
bool set_long (long value);
|
||||
@@ -1386,7 +1647,6 @@ private:
|
||||
*/
|
||||
const char * make_string () const;
|
||||
|
||||
|
||||
/**
|
||||
* Trace a read access.
|
||||
*/
|
||||
@@ -1409,29 +1669,22 @@ private:
|
||||
|
||||
int _index;
|
||||
std::string _name;
|
||||
mutable std::string _display_name;
|
||||
/// To avoid cyclic reference counting loops this shall not be a reference
|
||||
/// counted pointer
|
||||
SGPropertyNode * _parent;
|
||||
std::vector<SGPropertyNode_ptr> _children;
|
||||
std::vector<SGPropertyNode_ptr> _removedChildren;
|
||||
simgear::PropertyList _children;
|
||||
simgear::PropertyList _removedChildren;
|
||||
std::vector<hash_table *> _linkedNodes;
|
||||
mutable std::string _path;
|
||||
mutable std::string _buffer;
|
||||
hash_table * _path_cache;
|
||||
Type _type;
|
||||
simgear::props::Type _type;
|
||||
bool _tied;
|
||||
int _attr;
|
||||
|
||||
// The right kind of pointer...
|
||||
// The right kind of pointer...
|
||||
union {
|
||||
SGPropertyNode * alias;
|
||||
SGRawValue<bool> * bool_val;
|
||||
SGRawValue<int> * int_val;
|
||||
SGRawValue<long> * long_val;
|
||||
SGRawValue<float> * float_val;
|
||||
SGRawValue<double> * double_val;
|
||||
SGRawValue<const char *> * string_val;
|
||||
SGRaw* val;
|
||||
} _value;
|
||||
|
||||
union {
|
||||
@@ -1447,8 +1700,8 @@ private:
|
||||
|
||||
|
||||
/**
|
||||
* Register/unregister node that links to this node in its path cache.
|
||||
*/
|
||||
* Register/unregister node that links to this node in its path cache.
|
||||
*/
|
||||
void add_linked_node (hash_table * node) { _linkedNodes.push_back(node); }
|
||||
bool remove_linked_node (hash_table * node);
|
||||
|
||||
@@ -1505,10 +1758,21 @@ private:
|
||||
unsigned int _data_length;
|
||||
bucket ** _data;
|
||||
};
|
||||
|
||||
// Pass name as a pair of iterators
|
||||
template<typename Itr>
|
||||
SGPropertyNode * getChildImpl (Itr begin, Itr end, int index = 0, bool create = false);
|
||||
// very internal method
|
||||
template<typename Itr>
|
||||
SGPropertyNode* getExistingChild (Itr begin, Itr end, int index, bool create);
|
||||
// very internal path parsing function
|
||||
template<typename SplitItr>
|
||||
friend SGPropertyNode* find_node_aux(SGPropertyNode * current, SplitItr& itr,
|
||||
bool create, int last_index);
|
||||
// For boost
|
||||
friend size_t hash_value(const SGPropertyNode& node);
|
||||
};
|
||||
|
||||
// Convenice functions for use in templates
|
||||
// Convenience functions for use in templates
|
||||
template<typename T>
|
||||
T getValue(const SGPropertyNode*);
|
||||
|
||||
@@ -1574,6 +1838,169 @@ inline bool setValue (SGPropertyNode* node, const std::string& value)
|
||||
return node->setStringValue(value.c_str());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SGPropertyNode::tie(const SGRawValue<T> &rawValue, bool useDefault)
|
||||
{
|
||||
using namespace simgear::props;
|
||||
if (_type == ALIAS || _tied)
|
||||
return false;
|
||||
|
||||
useDefault = useDefault && hasValue();
|
||||
T old_val = SGRawValue<T>::DefaultValue();
|
||||
if (useDefault)
|
||||
old_val = getValue<T>(this);
|
||||
clearValue();
|
||||
if (PropertyTraits<T>::Internal)
|
||||
_type = PropertyTraits<T>::type_tag;
|
||||
else
|
||||
_type = EXTENDED;
|
||||
_tied = true;
|
||||
_value.val = rawValue.clone();
|
||||
if (useDefault)
|
||||
setValue(old_val);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool SGPropertyNode::tie (const SGRawValue<const char *> &rawValue,
|
||||
bool useDefault);
|
||||
|
||||
template<typename T>
|
||||
T SGPropertyNode::getValue(typename boost::disable_if_c<simgear::props
|
||||
::PropertyTraits<T>::Internal>::type* dummy) const
|
||||
{
|
||||
using namespace simgear::props;
|
||||
if (_attr == (READ|WRITE) && _type == EXTENDED
|
||||
&& _value.val->getType() == PropertyTraits<T>::type_tag) {
|
||||
return static_cast<SGRawValue<T>*>(_value.val)->getValue();
|
||||
}
|
||||
if (getAttribute(TRACE_READ))
|
||||
trace_read();
|
||||
if (!getAttribute(READ))
|
||||
return SGRawValue<T>::DefaultValue();
|
||||
switch (_type) {
|
||||
case EXTENDED:
|
||||
if (_value.val->getType() == PropertyTraits<T>::type_tag)
|
||||
return static_cast<SGRawValue<T>*>(_value.val)->getValue();
|
||||
break;
|
||||
case STRING:
|
||||
case UNSPECIFIED:
|
||||
return simgear::parseString<T>(make_string());
|
||||
break;
|
||||
default: // avoid compiler warning
|
||||
break;
|
||||
}
|
||||
return SGRawValue<T>::DefaultValue();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T SGPropertyNode::getValue(typename boost::enable_if_c<simgear::props
|
||||
::PropertyTraits<T>::Internal>::type* dummy) const
|
||||
{
|
||||
return ::getValue<T>(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SGPropertyNode::setValue(const T& val,
|
||||
typename boost::disable_if_c<simgear::props
|
||||
::PropertyTraits<T>::Internal>::type* dummy)
|
||||
{
|
||||
using namespace simgear::props;
|
||||
if (_attr == (READ|WRITE) && _type == EXTENDED
|
||||
&& _value.val->getType() == PropertyTraits<T>::type_tag) {
|
||||
static_cast<SGRawValue<T>*>(_value.val)->setValue(val);
|
||||
return true;
|
||||
}
|
||||
if (getAttribute(WRITE)
|
||||
&& ((_type == EXTENDED
|
||||
&& _value.val->getType() == PropertyTraits<T>::type_tag)
|
||||
|| _type == NONE || _type == UNSPECIFIED)) {
|
||||
if (_type == NONE || _type == UNSPECIFIED) {
|
||||
clearValue();
|
||||
_type = EXTENDED;
|
||||
_value.val = new SGRawValueContainer<T>(val);
|
||||
} else {
|
||||
static_cast<SGRawValue<T>*>(_value.val)->setValue(val);
|
||||
}
|
||||
if (getAttribute(TRACE_WRITE))
|
||||
trace_write();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool SGPropertyNode::setValue(const T& val,
|
||||
typename boost::enable_if_c<simgear::props
|
||||
::PropertyTraits<T>::Internal>::type* dummy)
|
||||
{
|
||||
return ::setValue(this, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for creation of a child property node.
|
||||
*/
|
||||
inline SGPropertyNode* makeChild(SGPropertyNode* parent, const char* name,
|
||||
int index = 0)
|
||||
{
|
||||
return parent->getChild(name, index, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for creation of a child property node using a
|
||||
* relative path.
|
||||
*/
|
||||
namespace simgear
|
||||
{
|
||||
template<typename StringType>
|
||||
inline SGPropertyNode* makeNode(SGPropertyNode* parent, const StringType& name)
|
||||
{
|
||||
return parent->getNode(name, true);
|
||||
}
|
||||
}
|
||||
|
||||
// For boost::hash
|
||||
size_t hash_value(const SGPropertyNode& node);
|
||||
|
||||
// Helper comparison and hash functions for common cases
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
namespace props
|
||||
{
|
||||
struct Compare
|
||||
{
|
||||
bool operator()(const SGPropertyNode* lhs, const SGPropertyNode* rhs) const
|
||||
{
|
||||
return SGPropertyNode::compare(*lhs, *rhs);
|
||||
}
|
||||
bool operator()(SGPropertyNode_ptr lhs, const SGPropertyNode* rhs) const
|
||||
{
|
||||
return SGPropertyNode::compare(*lhs, *rhs);
|
||||
}
|
||||
bool operator()(const SGPropertyNode* lhs, SGPropertyNode_ptr rhs) const
|
||||
{
|
||||
return SGPropertyNode::compare(*lhs, *rhs);
|
||||
}
|
||||
bool operator()(SGPropertyNode_ptr lhs, SGPropertyNode_ptr rhs) const
|
||||
{
|
||||
return SGPropertyNode::compare(*lhs, *rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct Hash
|
||||
{
|
||||
size_t operator()(const SGPropertyNode* node) const
|
||||
{
|
||||
return hash_value(*node);
|
||||
}
|
||||
size_t operator()(SGPropertyNode_ptr node) const
|
||||
{
|
||||
return hash_value(*node);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // __PROPS_HXX
|
||||
|
||||
// end of props.hxx
|
||||
|
||||
+70
-33
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
|
||||
@@ -27,6 +28,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring> // strcmp()
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
@@ -52,8 +54,11 @@ class PropsVisitor : public XMLVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
PropsVisitor (SGPropertyNode * root, const string &base, int default_mode = 0)
|
||||
: _default_mode(default_mode), _root(root), _level(0), _base(base), _hasException(false) {}
|
||||
PropsVisitor (SGPropertyNode * root, const string &base, int default_mode = 0,
|
||||
bool extended = false)
|
||||
: _default_mode(default_mode), _root(root), _level(0), _base(base),
|
||||
_hasException(false), _extended(extended)
|
||||
{}
|
||||
|
||||
virtual ~PropsVisitor () {}
|
||||
|
||||
@@ -110,6 +115,7 @@ private:
|
||||
string _base;
|
||||
sg_io_exception _exception;
|
||||
bool _hasException;
|
||||
bool _extended;
|
||||
};
|
||||
|
||||
void
|
||||
@@ -167,7 +173,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
|
||||
SGPath path(SGPath(_base).dir());
|
||||
path.append(attval);
|
||||
try {
|
||||
readProperties(path.str(), _root);
|
||||
readProperties(path.str(), _root, 0, _extended);
|
||||
} catch (sg_io_exception &e) {
|
||||
setException(e);
|
||||
}
|
||||
@@ -181,16 +187,17 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
|
||||
// Get the index.
|
||||
attval = atts.getValue("n");
|
||||
int index = 0;
|
||||
string strName(name);
|
||||
if (attval != 0) {
|
||||
index = atoi(attval);
|
||||
st.counters[name] = SG_MAX2(st.counters[name], index+1);
|
||||
st.counters[strName] = SG_MAX2(st.counters[strName], index+1);
|
||||
} else {
|
||||
index = st.counters[name];
|
||||
st.counters[name]++;
|
||||
index = st.counters[strName];
|
||||
st.counters[strName]++;
|
||||
}
|
||||
|
||||
// Got the index, so grab the node.
|
||||
SGPropertyNode * node = st.node->getChild(name, index, true);
|
||||
SGPropertyNode * node = st.node->getChild(strName, index, true);
|
||||
if (!node->getAttribute(SGPropertyNode::WRITE)) {
|
||||
SG_LOG(SG_INPUT, SG_ALERT, "Not overwriting write-protected property "
|
||||
<< node->getPath(true));
|
||||
@@ -235,7 +242,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
|
||||
SGPath path(SGPath(_base).dir());
|
||||
path.append(attval);
|
||||
try {
|
||||
readProperties(path.str(), node);
|
||||
readProperties(path.str(), node, 0, _extended);
|
||||
} catch (sg_io_exception &e) {
|
||||
setException(e);
|
||||
}
|
||||
@@ -275,6 +282,12 @@ PropsVisitor::endElement (const char * name)
|
||||
ret = st.node->setDoubleValue(strtod(_data.c_str(), 0));
|
||||
} else if (st.type == "string") {
|
||||
ret = st.node->setStringValue(_data.c_str());
|
||||
} else if (st.type == "vec3d" && _extended) {
|
||||
ret = st.node
|
||||
->setValue(simgear::parseString<SGVec3d>(_data));
|
||||
} else if (st.type == "vec4d" && _extended) {
|
||||
ret = st.node
|
||||
->setValue(simgear::parseString<SGVec4d>(_data));
|
||||
} else if (st.type == "unspecified") {
|
||||
ret = st.node->setUnspecifiedValue(_data.c_str());
|
||||
} else if (_level == 1) {
|
||||
@@ -344,9 +357,9 @@ PropsVisitor::warning (const char * message, int line, int column)
|
||||
*/
|
||||
void
|
||||
readProperties (istream &input, SGPropertyNode * start_node,
|
||||
const string &base, int default_mode)
|
||||
const string &base, int default_mode, bool extended)
|
||||
{
|
||||
PropsVisitor visitor(start_node, base, default_mode);
|
||||
PropsVisitor visitor(start_node, base, default_mode, extended);
|
||||
readXML(input, visitor, base);
|
||||
if (visitor.hasException())
|
||||
throw visitor.getException();
|
||||
@@ -362,9 +375,9 @@ readProperties (istream &input, SGPropertyNode * start_node,
|
||||
*/
|
||||
void
|
||||
readProperties (const string &file, SGPropertyNode * start_node,
|
||||
int default_mode)
|
||||
int default_mode, bool extended)
|
||||
{
|
||||
PropsVisitor visitor(start_node, file, default_mode);
|
||||
PropsVisitor visitor(start_node, file, default_mode, extended);
|
||||
readXML(file, visitor);
|
||||
if (visitor.hasException())
|
||||
throw visitor.getException();
|
||||
@@ -380,9 +393,10 @@ readProperties (const string &file, SGPropertyNode * start_node,
|
||||
* @return true if the read succeeded, false otherwise.
|
||||
*/
|
||||
void readProperties (const char *buf, const int size,
|
||||
SGPropertyNode * start_node, int default_mode)
|
||||
SGPropertyNode * start_node, int default_mode,
|
||||
bool extended)
|
||||
{
|
||||
PropsVisitor visitor(start_node, "", default_mode);
|
||||
PropsVisitor visitor(start_node, "", default_mode, extended);
|
||||
readXML(buf, size, visitor);
|
||||
if (visitor.hasException())
|
||||
throw visitor.getException();
|
||||
@@ -399,26 +413,33 @@ void readProperties (const char *buf, const int size,
|
||||
* Return the type name.
|
||||
*/
|
||||
static const char *
|
||||
getTypeName (SGPropertyNode::Type type)
|
||||
getTypeName (simgear::props::Type type)
|
||||
{
|
||||
using namespace simgear;
|
||||
switch (type) {
|
||||
case SGPropertyNode::UNSPECIFIED:
|
||||
case props::UNSPECIFIED:
|
||||
return "unspecified";
|
||||
case SGPropertyNode::BOOL:
|
||||
case props::BOOL:
|
||||
return "bool";
|
||||
case SGPropertyNode::INT:
|
||||
case props::INT:
|
||||
return "int";
|
||||
case SGPropertyNode::LONG:
|
||||
case props::LONG:
|
||||
return "long";
|
||||
case SGPropertyNode::FLOAT:
|
||||
case props::FLOAT:
|
||||
return "float";
|
||||
case SGPropertyNode::DOUBLE:
|
||||
case props::DOUBLE:
|
||||
return "double";
|
||||
case SGPropertyNode::STRING:
|
||||
case props::STRING:
|
||||
return "string";
|
||||
case SGPropertyNode::ALIAS:
|
||||
case SGPropertyNode::NONE:
|
||||
case props::VEC3D:
|
||||
return "vec3d";
|
||||
case props::VEC4D:
|
||||
return "vec4d";
|
||||
case props::ALIAS:
|
||||
case props::NONE:
|
||||
return "unspecified";
|
||||
default: // avoid compiler warning
|
||||
break;
|
||||
}
|
||||
|
||||
// keep the compiler from squawking
|
||||
@@ -524,7 +545,7 @@ writeNode (ostream &output, const SGPropertyNode * node,
|
||||
output << " alias=\"" << node->getAliasTarget()->getPath()
|
||||
<< "\"/>" << endl;
|
||||
} else {
|
||||
if (node->getType() != SGPropertyNode::UNSPECIFIED)
|
||||
if (node->getType() != simgear::props::UNSPECIFIED)
|
||||
output << " type=\"" << getTypeName(node->getType()) << '"';
|
||||
output << '>';
|
||||
writeData(output, node->getStringValue());
|
||||
@@ -581,6 +602,13 @@ writeProperties (const string &file, const SGPropertyNode * start_node,
|
||||
}
|
||||
}
|
||||
|
||||
// Another variation, useful when called from gdb
|
||||
void
|
||||
writeProperties (const char* file, const SGPropertyNode * start_node)
|
||||
{
|
||||
writeProperties(string(file), start_node, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -599,40 +627,49 @@ writeProperties (const string &file, const SGPropertyNode * start_node,
|
||||
bool
|
||||
copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
|
||||
{
|
||||
using namespace simgear;
|
||||
bool retval = true;
|
||||
|
||||
// First, copy the actual value,
|
||||
// if any.
|
||||
if (in->hasValue()) {
|
||||
switch (in->getType()) {
|
||||
case SGPropertyNode::BOOL:
|
||||
case props::BOOL:
|
||||
if (!out->setBoolValue(in->getBoolValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::INT:
|
||||
case props::INT:
|
||||
if (!out->setIntValue(in->getIntValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::LONG:
|
||||
case props::LONG:
|
||||
if (!out->setLongValue(in->getLongValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::FLOAT:
|
||||
case props::FLOAT:
|
||||
if (!out->setFloatValue(in->getFloatValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::DOUBLE:
|
||||
case props::DOUBLE:
|
||||
if (!out->setDoubleValue(in->getDoubleValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::STRING:
|
||||
case props::STRING:
|
||||
if (!out->setStringValue(in->getStringValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::UNSPECIFIED:
|
||||
case props::UNSPECIFIED:
|
||||
if (!out->setUnspecifiedValue(in->getStringValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case props::VEC3D:
|
||||
if (!out->setValue(in->getValue<SGVec3d>()))
|
||||
retval = false;
|
||||
break;
|
||||
case props::VEC4D:
|
||||
if (!out->setValue(in->getValue<SGVec4d>()))
|
||||
retval = false;
|
||||
break;
|
||||
default:
|
||||
if (in->isAlias())
|
||||
break;
|
||||
@@ -649,7 +686,7 @@ copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
|
||||
int nChildren = in->nChildren();
|
||||
for (int i = 0; i < nChildren; i++) {
|
||||
const SGPropertyNode * in_child = in->getChild(i);
|
||||
SGPropertyNode * out_child = out->getChild(in_child->getName(),
|
||||
SGPropertyNode * out_child = out->getChild(in_child->getNameString(),
|
||||
in_child->getIndex(),
|
||||
true);
|
||||
if (!copyProperties(in_child, out_child))
|
||||
|
||||
@@ -26,21 +26,23 @@
|
||||
* Read properties from an XML input stream.
|
||||
*/
|
||||
void readProperties (std::istream &input, SGPropertyNode * start_node,
|
||||
const std::string &base = "", int default_mode = 0);
|
||||
const std::string &base = "", int default_mode = 0,
|
||||
bool extended = false);
|
||||
|
||||
|
||||
/**
|
||||
* Read properties from an XML file.
|
||||
*/
|
||||
void readProperties (const std::string &file, SGPropertyNode * start_node,
|
||||
int default_mode = 0);
|
||||
int default_mode = 0, bool extended = false);
|
||||
|
||||
|
||||
/**
|
||||
* Read properties from an in-memory buffer.
|
||||
*/
|
||||
void readProperties (const char *buf, const int size,
|
||||
SGPropertyNode * start_node, int default_mode = 0);
|
||||
SGPropertyNode * start_node, int default_mode = 0,
|
||||
bool extended = false);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -324,6 +324,26 @@ test_property_nodes ()
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
void test_addChild()
|
||||
{
|
||||
SGPropertyNode root;
|
||||
|
||||
cout << "Testing the addChild function " << endl;
|
||||
cout << "Created root node " << root.getPath() << endl;
|
||||
|
||||
SGPropertyNode *test = root.getChild("test", 0, true);
|
||||
SGPropertyNode *n = test->getNode("foo", true);
|
||||
n->getChild("child", 1, true)->setIntValue(1);
|
||||
n->getChild("child", 2, true)->setIntValue(2);
|
||||
n->getChild("child", 4, true)->setIntValue(2);
|
||||
dump_node(&root);
|
||||
|
||||
SGPropertyNode *ch = n->addChild("child");
|
||||
ch->setIntValue(3);
|
||||
cerr << endl << "ADDED: " << ch->getPath() << endl << endl;
|
||||
dump_node(&root);
|
||||
}
|
||||
|
||||
|
||||
int main (int ac, char ** av)
|
||||
{
|
||||
@@ -342,5 +362,7 @@ int main (int ac, char ** av)
|
||||
}
|
||||
}
|
||||
|
||||
test_addChild();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -31,4 +31,5 @@ routetest_LDADD = \
|
||||
libsgroute.a \
|
||||
$(top_builddir)/simgear/math/libsgmath.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/structure/libsgstructure.a \
|
||||
$(base_LIBS)
|
||||
|
||||
+26
-44
@@ -20,6 +20,9 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <plib/sg.h>
|
||||
|
||||
@@ -38,51 +41,22 @@ SGRoute::SGRoute() {
|
||||
SGRoute::~SGRoute() {
|
||||
}
|
||||
|
||||
|
||||
// Calculate perpendicular distance from the current route segment
|
||||
// This routine assumes all points are laying on a flat plane and
|
||||
// ignores the altitude (or Z) dimension. For best results, use with
|
||||
// CARTESIAN way points.
|
||||
double SGRoute::distance_off_route( double x, double y ) const {
|
||||
if ( current_wp > 0 ) {
|
||||
int n0 = current_wp - 1;
|
||||
int n1 = current_wp;
|
||||
sgdVec3 p, p0, p1, d;
|
||||
sgdSetVec3( p, x, y, 0.0 );
|
||||
sgdSetVec3( p0,
|
||||
route[n0].get_target_lon(), route[n0].get_target_lat(),
|
||||
0.0 );
|
||||
sgdSetVec3( p1,
|
||||
route[n1].get_target_lon(), route[n1].get_target_lat(),
|
||||
0.0 );
|
||||
sgdSubVec3( d, p0, p1 );
|
||||
|
||||
return sqrt( sgdClosestPointToLineDistSquared( p, p0, d ) );
|
||||
|
||||
} else {
|
||||
// We are tracking the first waypoint so there is no route
|
||||
// segment. If you add the current location as the first
|
||||
// waypoint and the actual waypoint as the second, then we
|
||||
// will have a route segment and calculate distance from it.
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Update the length of the leg ending at waypoint index */
|
||||
void SGRoute::update_distance(int index)
|
||||
void SGRoute::update_distance_and_track(int index)
|
||||
{
|
||||
SGWayPoint& curr = route[ index ];
|
||||
double course, dist;
|
||||
SGWayPoint& curr = route[ index ];
|
||||
double course, dist;
|
||||
|
||||
if ( index == 0 ) {
|
||||
dist = 0;
|
||||
} else {
|
||||
const SGWayPoint& prev = route[ index - 1 ];
|
||||
curr.CourseAndDistance( prev, &course, &dist );
|
||||
}
|
||||
if ( index == 0 ) {
|
||||
dist = 0;
|
||||
course = 0.0;
|
||||
} else {
|
||||
const SGWayPoint& prev = route[index - 1];
|
||||
curr.CourseAndDistance( prev, &course, &dist );
|
||||
}
|
||||
|
||||
curr.set_distance( dist );
|
||||
curr.set_distance(dist);
|
||||
curr.set_track(course);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,9 +71,9 @@ void SGRoute::add_waypoint( const SGWayPoint &wp, int n ) {
|
||||
} else {
|
||||
route.insert( route.begin() + n, 1, wp );
|
||||
// update distance of next leg if not at end of route
|
||||
update_distance( n + 1 );
|
||||
update_distance_and_track( n + 1 );
|
||||
}
|
||||
update_distance( n );
|
||||
update_distance_and_track( n );
|
||||
}
|
||||
|
||||
/** Delete waypoint with index n (last one if n < 0) */
|
||||
@@ -113,5 +87,13 @@ void SGRoute::delete_waypoint( int n ) {
|
||||
route.erase( route.begin() + n );
|
||||
// update distance of next leg if not at end of route
|
||||
if ( n < size - 1 )
|
||||
update_distance( n );
|
||||
update_distance_and_track( n );
|
||||
}
|
||||
|
||||
double SGRoute::total_distance() const {
|
||||
double total = 0.0;
|
||||
for (unsigned int i=0; i<route.size(); ++i) {
|
||||
total += route[i].get_distance();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
+24
-7
@@ -52,7 +52,7 @@ private:
|
||||
route_list route;
|
||||
int current_wp;
|
||||
|
||||
void update_distance(int index);
|
||||
void update_distance_and_track(int index);
|
||||
|
||||
public:
|
||||
|
||||
@@ -102,6 +102,22 @@ public:
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
inline SGWayPoint get_previous() const {
|
||||
if ( (current_wp > 0) && (current_wp < (int)route.size()) ) {
|
||||
return route[current_wp - 1];
|
||||
} else {
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
inline SGWayPoint get_next() const {
|
||||
if ( (current_wp + 1) < (int)route.size() ) {
|
||||
return route[current_wp+1];
|
||||
} else {
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current waypoint
|
||||
@@ -113,6 +129,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline int current_index() const {
|
||||
return current_wp;
|
||||
}
|
||||
|
||||
/** Increment the current waypoint pointer. */
|
||||
inline void increment_current() {
|
||||
if ( current_wp < (int)route.size() - 1 ) {
|
||||
@@ -138,14 +158,11 @@ public:
|
||||
|
||||
/** Delete waypoint waypoint with index n (last one if n < 0) */
|
||||
void delete_waypoint( int n = 0 );
|
||||
|
||||
|
||||
/**
|
||||
* Calculate perpendicular distance from the current route segment
|
||||
* This routine assumes all points are laying on a flat plane and
|
||||
* ignores the altitude (or Z) dimension. For most accurate
|
||||
* results, use with CARTESIAN way points.
|
||||
* Helper, sum the distance members of each waypoint
|
||||
*/
|
||||
double distance_off_route( double x, double y ) const;
|
||||
double total_distance() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ void dump_route(const SGRoute& route, const char* message)
|
||||
int main()
|
||||
{
|
||||
SGRoute route;
|
||||
|
||||
/*
|
||||
route.add_waypoint( SGWayPoint(0, 0, 0, SGWayPoint::CARTESIAN, "Start") );
|
||||
route.add_waypoint( SGWayPoint(1, 0, 0, SGWayPoint::CARTESIAN, "1") );
|
||||
route.add_waypoint( SGWayPoint(2, 0, 0, SGWayPoint::CARTESIAN, "2") );
|
||||
@@ -48,6 +48,6 @@ int main()
|
||||
|
||||
route.add_waypoint(wp2, 3);
|
||||
dump_route(route, "added back WP2 after WP3");
|
||||
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
+24
-32
@@ -29,23 +29,38 @@
|
||||
|
||||
#include "waypoint.hxx"
|
||||
|
||||
using std::string;
|
||||
|
||||
// Constructor
|
||||
SGWayPoint::SGWayPoint( const double lon, const double lat, const double alt,
|
||||
const modetype m, const string& s, const string& n ) {
|
||||
target_lon = lon;
|
||||
target_lat = lat;
|
||||
target_alt = alt;
|
||||
mode = m;
|
||||
id = s;
|
||||
name = n;
|
||||
const modetype, const string& s, const string& n ) :
|
||||
pos(SGGeod::fromDegM(lon, lat, alt)),
|
||||
id(s),
|
||||
name(n),
|
||||
_distance(0.0),
|
||||
_track(0.0),
|
||||
_speed(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
SGWayPoint::SGWayPoint(const SGGeod& geod, const string& s, const string& n ) :
|
||||
pos(geod),
|
||||
id(s),
|
||||
name(n),
|
||||
_distance(0.0),
|
||||
_track(0.0),
|
||||
_speed(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
SGWayPoint::~SGWayPoint() {
|
||||
}
|
||||
|
||||
void SGWayPoint::CourseAndDistance(const SGGeod& cur, double& course, double& dist ) const {
|
||||
double reverse;
|
||||
SGGeodesy::inverse(cur, pos, course, reverse, dist);
|
||||
}
|
||||
|
||||
// Calculate course and distances. For WGS84 and SPHERICAL
|
||||
// coordinates lat, lon, and course are in degrees, alt and distance
|
||||
@@ -55,34 +70,11 @@ void SGWayPoint::CourseAndDistance( const double cur_lon,
|
||||
const double cur_lat,
|
||||
const double cur_alt,
|
||||
double *course, double *dist ) const {
|
||||
if ( mode == WGS84 ) {
|
||||
double reverse;
|
||||
geo_inverse_wgs_84( cur_alt, cur_lat, cur_lon, target_lat, target_lon,
|
||||
course, &reverse, dist );
|
||||
} else if ( mode == SPHERICAL ) {
|
||||
Point3D current( cur_lon * SGD_DEGREES_TO_RADIANS, cur_lat * SGD_DEGREES_TO_RADIANS, 0.0 );
|
||||
Point3D target( target_lon * SGD_DEGREES_TO_RADIANS, target_lat * SGD_DEGREES_TO_RADIANS, 0.0 );
|
||||
calc_gc_course_dist( current, target, course, dist );
|
||||
*course = 360.0 - *course * SGD_RADIANS_TO_DEGREES;
|
||||
} else if ( mode == CARTESIAN ) {
|
||||
double dx = target_lon - cur_lon;
|
||||
double dy = target_lat - cur_lat;
|
||||
*course = -atan2( dy, dx ) * SGD_RADIANS_TO_DEGREES - 90;
|
||||
while ( *course < 0 ) {
|
||||
*course += 360.0;
|
||||
}
|
||||
while ( *course > 360.0 ) {
|
||||
*course -= 360.0;
|
||||
}
|
||||
*dist = sqrt( dx * dx + dy * dy );
|
||||
}
|
||||
CourseAndDistance(SGGeod::fromDegM(cur_lon, cur_lat, cur_alt), *course, *dist);
|
||||
}
|
||||
|
||||
// Calculate course and distances between two waypoints
|
||||
void SGWayPoint::CourseAndDistance( const SGWayPoint &wp,
|
||||
double *course, double *dist ) const {
|
||||
CourseAndDistance( wp.get_target_lon(),
|
||||
wp.get_target_lat(),
|
||||
wp.get_target_alt(),
|
||||
course, dist );
|
||||
CourseAndDistance( wp.get_target(), *course, *dist );
|
||||
}
|
||||
|
||||
+42
-34
@@ -27,17 +27,12 @@
|
||||
#ifndef _WAYPOINT_HXX
|
||||
#define _WAYPOINT_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <string>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
|
||||
using std::string;
|
||||
#include <string>
|
||||
|
||||
|
||||
/**
|
||||
@@ -57,27 +52,21 @@ public:
|
||||
* the world is a perfect sphere. This is less compuntationally
|
||||
* expensive than using wgs84 math and still a fairly good
|
||||
* approximation of the real world, especially over shorter distances.
|
||||
* <li> CARTESIAN requests all math be done assuming the coordinates specify
|
||||
* position in a Z = up world.
|
||||
*/
|
||||
enum modetype {
|
||||
WGS84 = 0,
|
||||
SPHERICAL = 1,
|
||||
CARTESIAN = 2
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
modetype mode;
|
||||
|
||||
double target_lon;
|
||||
double target_lat;
|
||||
double target_alt;
|
||||
double distance;
|
||||
|
||||
string id;
|
||||
string name;
|
||||
|
||||
SGGeod pos;
|
||||
std::string id;
|
||||
std::string name;
|
||||
|
||||
// route data associated with the waypoint
|
||||
double _distance;
|
||||
double _track;
|
||||
double _speed;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -91,7 +80,12 @@ public:
|
||||
*/
|
||||
SGWayPoint( const double lon = 0.0, const double lat = 0.0,
|
||||
const double alt = 0.0, const modetype m = WGS84,
|
||||
const string& s = "", const string& n = "" );
|
||||
const std::string& s = "", const std::string& n = "" );
|
||||
|
||||
/**
|
||||
* Construct from a geodetic position, in WGS84 coordinates
|
||||
*/
|
||||
SGWayPoint(const SGGeod& pos, const std::string& s, const std::string& n);
|
||||
|
||||
/** Destructor */
|
||||
~SGWayPoint();
|
||||
@@ -112,6 +106,9 @@ public:
|
||||
const double cur_alt,
|
||||
double *course, double *dist ) const;
|
||||
|
||||
void CourseAndDistance(const SGGeod& current,
|
||||
double& course, double& dist ) const;
|
||||
|
||||
/**
|
||||
* Calculate course and distances between a specified starting waypoint
|
||||
* and this waypoint.
|
||||
@@ -122,17 +119,22 @@ public:
|
||||
void CourseAndDistance( const SGWayPoint &wp,
|
||||
double *course, double *dist ) const;
|
||||
|
||||
/** @return waypoint mode */
|
||||
inline modetype get_mode() const { return mode; }
|
||||
|
||||
/** @return waypoint longitude */
|
||||
inline double get_target_lon() const { return target_lon; }
|
||||
inline double get_target_lon() const { return pos.getLongitudeDeg(); }
|
||||
|
||||
/** @return waypoint latitude */
|
||||
inline double get_target_lat() const { return target_lat; }
|
||||
inline double get_target_lat() const { return pos.getLatitudeDeg(); }
|
||||
|
||||
/** @return waypoint altitude */
|
||||
inline double get_target_alt() const { return target_alt; }
|
||||
inline double get_target_alt() const { return pos.getElevationM(); }
|
||||
|
||||
inline const SGGeod& get_target() const { return pos; }
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
inline void setTargetAltFt(double elev)
|
||||
{ pos.setElevationFt(elev); }
|
||||
|
||||
/**
|
||||
* This value is not calculated by this class. It is simply a
|
||||
@@ -144,19 +146,25 @@ public:
|
||||
* is for your convenience only.
|
||||
* @return waypoint distance holder (what ever the user has stashed here)
|
||||
*/
|
||||
inline double get_distance() const { return distance; }
|
||||
inline double get_distance() const { return _distance; }
|
||||
|
||||
/**
|
||||
* Set the waypoint distance value to a value of our choice.
|
||||
* @param d distance
|
||||
*/
|
||||
inline void set_distance( double d ) { distance = d; }
|
||||
inline void set_distance( double d ) { _distance = d; }
|
||||
|
||||
inline double get_track() const { return _track; }
|
||||
inline void set_track(double t) { _track = t; }
|
||||
|
||||
inline double get_speed() const { return _speed; }
|
||||
inline void set_speed(double v) { _speed = v; }
|
||||
|
||||
/** @return waypoint id */
|
||||
inline const string& get_id() const { return id; }
|
||||
inline const std::string& get_id() const { return id; }
|
||||
|
||||
/** @return waypoint name */
|
||||
inline const string& get_name() const { return name; }
|
||||
inline const std::string& get_name() const { return name; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using std::endl;
|
||||
|
||||
int main() {
|
||||
SGWayPoint a1(-93.216923, 44.880547, 0.0, SGWayPoint::WGS84, "KMSP");
|
||||
SGWayPoint a2(-93.216923, 44.880547, 0.0, SGWayPoint::SPHERICAL, "KMSP");
|
||||
|
||||
|
||||
// KMSN (Madison)
|
||||
double cur_lon = -89.336939;
|
||||
@@ -24,43 +24,15 @@ int main() {
|
||||
cout << "Distance to " << a1.get_id() << " is " << distance * SG_METER_TO_NM
|
||||
<< endl;
|
||||
|
||||
a2.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << a2.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << a2.get_id() << " is " << distance * SG_METER_TO_NM
|
||||
<< endl;
|
||||
cout << endl;
|
||||
|
||||
SGWayPoint b1(-88.237037, 43.041038, 0.0, SGWayPoint::WGS84, "KUES");
|
||||
SGWayPoint b2(-88.237037, 43.041038, 0.0, SGWayPoint::SPHERICAL, "KUES");
|
||||
|
||||
|
||||
b1.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << b1.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << b1.get_id() << " is " << distance * SG_METER_TO_NM
|
||||
<< endl;
|
||||
|
||||
b2.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << b2.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << b2.get_id() << " is " << distance * SG_METER_TO_NM
|
||||
<< endl;
|
||||
cout << endl;
|
||||
|
||||
cur_lon = 10;
|
||||
cur_lat = 10;
|
||||
|
||||
SGWayPoint c1(-20, 10, 0, SGWayPoint::CARTESIAN, "Due East");
|
||||
c1.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << c1.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << c1.get_id() << " is " << distance << endl;
|
||||
|
||||
SGWayPoint c2(20, 20, 0, SGWayPoint::CARTESIAN, "Due SW");
|
||||
c2.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << c2.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << c2.get_id() << " is " << distance << endl;
|
||||
|
||||
SGWayPoint c3(20, 0, 0, SGWayPoint::CARTESIAN, "Due NW");
|
||||
c3.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << c3.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << c3.get_id() << " is " << distance << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
includedir = @includedir@/scene
|
||||
|
||||
SUBDIRS = material model sky tgdb util
|
||||
SUBDIRS = bvh material model sky tgdb util
|
||||
|
||||
# lib_LIBRARIES = libsgscene.a
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef BVHBoundingBoxVisitor_hxx
|
||||
#define BVHBoundingBoxVisitor_hxx
|
||||
|
||||
#include <simgear/math/SGGeometry.hxx>
|
||||
|
||||
#include "BVHVisitor.hxx"
|
||||
#include "BVHNode.hxx"
|
||||
#include "BVHGroup.hxx"
|
||||
#include "BVHTransform.hxx"
|
||||
#include "BVHMotionTransform.hxx"
|
||||
#include "BVHLineGeometry.hxx"
|
||||
|
||||
#include "BVHStaticData.hxx"
|
||||
|
||||
#include "BVHStaticNode.hxx"
|
||||
#include "BVHStaticTriangle.hxx"
|
||||
#include "BVHStaticBinary.hxx"
|
||||
#include "BVHStaticGeometry.hxx"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
class BVHBoundingBoxVisitor : public BVHVisitor {
|
||||
public:
|
||||
virtual ~BVHBoundingBoxVisitor() {}
|
||||
|
||||
void clear()
|
||||
{ _box.clear(); }
|
||||
|
||||
virtual void apply(BVHGroup& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
virtual void apply(BVHTransform& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
virtual void apply(BVHMotionTransform& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
virtual void apply(BVHLineGeometry& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
virtual void apply(BVHStaticGeometry& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
|
||||
virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
|
||||
{ expandBy(node.getBoundingBox()); }
|
||||
virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
|
||||
{ expandBy(node.computeBoundingBox(data)); }
|
||||
|
||||
const SGBoxf& getBox() const
|
||||
{ return _box; }
|
||||
|
||||
private:
|
||||
void expandBy(const SGSphered& sphere)
|
||||
{
|
||||
SGVec3f v0(sphere.getCenter() - sphere.getRadius()*SGVec3d(1, 1, 1));
|
||||
SGVec3f v1(sphere.getCenter() + sphere.getRadius()*SGVec3d(1, 1, 1));
|
||||
_box.expandBy(SGBoxf(v0, v1));
|
||||
}
|
||||
void expandBy(const SGBoxf& box)
|
||||
{ _box.expandBy(box); }
|
||||
|
||||
SGBoxf _box;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,210 @@
|
||||
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef BVHDebugCollectVisitor_hxx
|
||||
#define BVHDebugCollectVisitor_hxx
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/PolygonOffset>
|
||||
#include <osg/PrimitiveSet>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/Shape>
|
||||
#include <osg/Depth>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/StateSet>
|
||||
|
||||
#include <simgear/math/SGGeometry.hxx>
|
||||
|
||||
#include "BVHVisitor.hxx"
|
||||
#include "BVHNode.hxx"
|
||||
#include "BVHGroup.hxx"
|
||||
#include "BVHTransform.hxx"
|
||||
#include "BVHMotionTransform.hxx"
|
||||
#include "BVHStaticGeometry.hxx"
|
||||
|
||||
#include "BVHStaticData.hxx"
|
||||
|
||||
#include "BVHStaticNode.hxx"
|
||||
#include "BVHStaticTriangle.hxx"
|
||||
#include "BVHStaticBinary.hxx"
|
||||
|
||||
#include "BVHBoundingBoxVisitor.hxx"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
class BVHNode;
|
||||
class BVHStaticNode;
|
||||
|
||||
class BVHDebugCollectVisitor : public BVHVisitor {
|
||||
public:
|
||||
BVHDebugCollectVisitor(const double& time, unsigned level = ~0u) :
|
||||
_group(new osg::Group),
|
||||
_time(time),
|
||||
_level(level),
|
||||
_currentLevel(0)
|
||||
{
|
||||
osg::StateSet* stateSet = _group->getOrCreateStateSet();
|
||||
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
stateSet->setAttribute(new osg::Depth(osg::Depth::LESS, 0, 1, false));
|
||||
osg::BlendFunc *blendFunc;
|
||||
blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA,
|
||||
osg::BlendFunc::DST_ALPHA);
|
||||
stateSet->setAttributeAndModes(blendFunc);
|
||||
osg::PolygonOffset* polygonOffset = new osg::PolygonOffset(-1, -1);
|
||||
stateSet->setAttributeAndModes(polygonOffset);
|
||||
}
|
||||
virtual ~BVHDebugCollectVisitor()
|
||||
{ }
|
||||
|
||||
virtual void apply(BVHGroup& node)
|
||||
{
|
||||
addNodeSphere(node);
|
||||
++_currentLevel;
|
||||
node.traverse(*this);
|
||||
--_currentLevel;
|
||||
}
|
||||
virtual void apply(BVHTransform& node)
|
||||
{
|
||||
addNodeSphere(node);
|
||||
osg::ref_ptr<osg::Group> oldGroup = _group;
|
||||
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
|
||||
transform->setMatrix(osg::Matrix(node.getToWorldTransform().data()));
|
||||
_group = transform;
|
||||
++_currentLevel;
|
||||
node.traverse(*this);
|
||||
--_currentLevel;
|
||||
_group = oldGroup;
|
||||
if (transform->getNumChildren())
|
||||
_group->addChild(transform.get());
|
||||
}
|
||||
virtual void apply(BVHMotionTransform& node)
|
||||
{
|
||||
addNodeSphere(node);
|
||||
osg::ref_ptr<osg::Group> oldGroup = _group;
|
||||
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
|
||||
transform->setMatrix(osg::Matrix(node.getToWorldTransform(_time).data()));
|
||||
_group = transform;
|
||||
++_currentLevel;
|
||||
node.traverse(*this);
|
||||
--_currentLevel;
|
||||
_group = oldGroup;
|
||||
if (transform->getNumChildren())
|
||||
_group->addChild(transform.get());
|
||||
}
|
||||
virtual void apply(BVHLineGeometry&)
|
||||
{
|
||||
}
|
||||
virtual void apply(BVHStaticGeometry& node)
|
||||
{
|
||||
addNodeSphere(node);
|
||||
++_currentLevel;
|
||||
node.traverse(*this);
|
||||
--_currentLevel;
|
||||
}
|
||||
|
||||
virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
|
||||
{
|
||||
addNodeBox(node, data);
|
||||
++_currentLevel;
|
||||
node.traverse(*this, data);
|
||||
--_currentLevel;
|
||||
}
|
||||
virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
|
||||
{
|
||||
addNodeBox(node, data);
|
||||
addTriangle(node.getTriangle(data), osg::Vec4(0.5, 0, 0.5, 0.2));
|
||||
}
|
||||
|
||||
osg::Node* getNode() const { return _group.get(); }
|
||||
|
||||
static unsigned allLevels() { return ~0u; }
|
||||
static unsigned triangles() { return ~0u - 1; }
|
||||
|
||||
private:
|
||||
void addTriangle(const SGTrianglef& triangle, const osg::Vec4& color)
|
||||
{
|
||||
if (_level != triangles())
|
||||
return;
|
||||
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
vertices->push_back(toOsg(triangle.getVertex(0)));
|
||||
vertices->push_back(toOsg(triangle.getVertex(1)));
|
||||
vertices->push_back(toOsg(triangle.getVertex(2)));
|
||||
|
||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
||||
colors->push_back(color);
|
||||
|
||||
geometry->setVertexArray(vertices);
|
||||
geometry->setColorArray(colors);
|
||||
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, 3));
|
||||
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(geometry);
|
||||
_group->addChild(geode);
|
||||
}
|
||||
|
||||
void addNodeSphere(const BVHNode& node)
|
||||
{
|
||||
if (_level != ~0u && _level != _currentLevel)
|
||||
return;
|
||||
SGSphered sphere = node.getBoundingSphere();
|
||||
osg::Sphere* shape = new osg::Sphere;
|
||||
shape->setCenter(toOsg(sphere.getCenter()));
|
||||
shape->setRadius(sphere.getRadius());
|
||||
addShape(shape, osg::Vec4(0.5f, 0.5f, 0.5f, 0.1f));
|
||||
}
|
||||
|
||||
void addNodeBox(const BVHStaticNode& node, const BVHStaticData& data)
|
||||
{
|
||||
if (_level != ~0u && _level != _currentLevel)
|
||||
return;
|
||||
BVHBoundingBoxVisitor bbv;
|
||||
node.accept(bbv, data);
|
||||
osg::Box* shape = new osg::Box;
|
||||
shape->setCenter(toOsg(bbv.getBox().getCenter()));
|
||||
shape->setHalfLengths(toOsg((0.5*bbv.getBox().getSize())));
|
||||
addShape(shape, osg::Vec4(0.5f, 0, 0, 0.1f));
|
||||
}
|
||||
|
||||
void addShape(osg::Shape* shape, const osg::Vec4& color)
|
||||
{
|
||||
osg::ShapeDrawable* shapeDrawable = new osg::ShapeDrawable;
|
||||
shapeDrawable->setColor(color);
|
||||
shapeDrawable->setShape(shape);
|
||||
osg::Geode* geode = new osg::Geode;
|
||||
geode->addDrawable(shapeDrawable);
|
||||
_group->addChild(geode);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Group> _group;
|
||||
const double _time;
|
||||
const unsigned _level;
|
||||
unsigned _currentLevel;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include "BVHGroup.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace simgear {
|
||||
|
||||
BVHGroup::BVHGroup()
|
||||
{
|
||||
}
|
||||
|
||||
BVHGroup::~BVHGroup()
|
||||
{
|
||||
ChildList::iterator i;
|
||||
for (i = _children.begin(); i != _children.end(); ++i) {
|
||||
(*i)->removeParent(this);
|
||||
*i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BVHGroup::accept(BVHVisitor& visitor)
|
||||
{
|
||||
visitor.apply(*this);
|
||||
}
|
||||
|
||||
void
|
||||
BVHGroup::clear()
|
||||
{
|
||||
_children.clear();
|
||||
invalidateBound();
|
||||
}
|
||||
|
||||
void
|
||||
BVHGroup::addChild(BVHNode* child)
|
||||
{
|
||||
if (!child)
|
||||
return;
|
||||
ChildList::iterator i;
|
||||
i = std::find(_children.begin(), _children.end(), child);
|
||||
if (i != _children.end())
|
||||
return;
|
||||
invalidateBound();
|
||||
child->addParent(this);
|
||||
_children.push_back(child);
|
||||
}
|
||||
|
||||
void
|
||||
BVHGroup::removeChild(BVHNode* child)
|
||||
{
|
||||
if (!child)
|
||||
return;
|
||||
ChildList::iterator i;
|
||||
i = std::find(_children.begin(), _children.end(), child);
|
||||
if (i == _children.end())
|
||||
return;
|
||||
invalidateBound();
|
||||
child->removeParent(this);
|
||||
_children.erase(i);
|
||||
}
|
||||
|
||||
SGSphered
|
||||
BVHGroup::computeBoundingSphere() const
|
||||
{
|
||||
SGSphered sphere;
|
||||
ChildList::const_iterator i;
|
||||
for (i = _children.begin(); i != _children.end(); ++i)
|
||||
sphere.expandBy((*i)->getBoundingSphere());
|
||||
return sphere;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef BVHGroup_hxx
|
||||
#define BVHGroup_hxx
|
||||
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
#include "BVHNode.hxx"
|
||||
#include "BVHVisitor.hxx"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
class BVHGroup : public BVHNode {
|
||||
public:
|
||||
BVHGroup();
|
||||
virtual ~BVHGroup();
|
||||
|
||||
virtual void accept(BVHVisitor& visitor);
|
||||
|
||||
void traverse(BVHVisitor& visitor)
|
||||
{
|
||||
ChildList::const_iterator i;
|
||||
for (i = _children.begin(); i != _children.end(); ++i)
|
||||
(*i)->accept(visitor);
|
||||
}
|
||||
|
||||
void clear();
|
||||
void addChild(BVHNode* child);
|
||||
void removeChild(BVHNode* child);
|
||||
|
||||
unsigned getNumChildren() const
|
||||
{ return _children.size(); }
|
||||
const BVHNode* getChild(unsigned i) const
|
||||
{ if (_children.size() <= i) return 0; return _children[i]; }
|
||||
BVHNode* getChild(unsigned i)
|
||||
{ if (_children.size() <= i) return 0; return _children[i]; }
|
||||
|
||||
virtual SGSphered computeBoundingSphere() const;
|
||||
|
||||
private:
|
||||
typedef std::vector<SGSharedPtr<BVHNode> > ChildList;
|
||||
ChildList _children;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user