Compare commits
439
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11479cd8c3 | ||
|
|
176e760de1 | ||
|
|
430c60ed1a | ||
|
|
dfea3623f6 | ||
|
|
b38783e4cb | ||
|
|
9382a4c21b | ||
|
|
3cd4c5566f | ||
|
|
601c0977df | ||
|
|
c56f036bab | ||
|
|
44dd50c0ef | ||
|
|
56919ae45f | ||
|
|
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
|
# This could be handy for archiving the generated documentation or
|
||||||
# if some version control system is used.
|
# 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)
|
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||||
# base path where the generated documentation will be put.
|
# base path where the generated documentation will be put.
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
Version 1.99.5
|
Version 1.9.0
|
||||||
* October 30, 2008 (sourcecode snapshot release)
|
* 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
|
New in 0.3.10
|
||||||
|
|||||||
+5
-2
@@ -3,16 +3,19 @@
|
|||||||
You *must* have OpenSceneGraph (OSG) installed to build this version of
|
You *must* have OpenSceneGraph (OSG) installed to build this version of
|
||||||
FlightGear.
|
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:
|
You can get the latest version of OSG from:
|
||||||
|
|
||||||
http://www.openscenegraph.org/
|
http://www.openscenegraph.org/
|
||||||
|
|
||||||
Build notes:
|
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:
|
commands:
|
||||||
|
|
||||||
unzip OpenSceneGraph-2.4
|
unzip OpenSceneGraph-x.x
|
||||||
cd OpenSceneGraph
|
cd OpenSceneGraph
|
||||||
ccmake .
|
ccmake .
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -3,27 +3,27 @@
|
|||||||
You *must* have the development components of OpenAL installed on your system
|
You *must* have the development components of OpenAL installed on your system
|
||||||
to build FlightGear!" You can get a copy here:
|
to build FlightGear!" You can get a copy here:
|
||||||
|
|
||||||
http://www.openal.org
|
http://connect.creativelabs.com/openal/default.aspx
|
||||||
|
|
||||||
Build notes:
|
Build notes:
|
||||||
|
|
||||||
You can download a versioned release of the openal library from
|
You can download a versioned release of the openal library from
|
||||||
http://www.openal.org/downloads.html. Download the openal source,
|
http://www.openal.org/downloads.html. Download the openal source,
|
||||||
release 0.0.8 (dated February 11, 2006) and run:
|
release 0.0.8 (dated February 11, 2006) and run:
|
||||||
tar xzvf openal-0.0.8.tar.gz
|
tar xjvf openal-soft-1.5.304.tar.bz2
|
||||||
cd openal-0.0.8
|
cd openal-soft-1.5.304/
|
||||||
./configure
|
ccmake .
|
||||||
make
|
|
||||||
sudo make install
|
[ 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
|
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
|
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
|
tar xzvf freelut-1.1.0.tar.gz
|
||||||
cd freelut-1.1.0
|
cd freealut-1.1.0
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
sudo make install
|
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>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
+224
@@ -460,3 +460,227 @@ pushdef([AC_PROG_INSTALL],
|
|||||||
INSTALL_PROGRAM='${INSTALL} $(INSTALL_STRIP_FLAG)'
|
INSTALL_PROGRAM='${INSTALL} $(INSTALL_STRIP_FLAG)'
|
||||||
INSTALL_SCRIPT='${INSTALL}'
|
INSTALL_SCRIPT='${INSTALL}'
|
||||||
])dnl
|
])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
|
||||||
|
|
||||||
|
])
|
||||||
|
|||||||
+133
-5
@@ -8,7 +8,7 @@ dnl Require at least automake 2.52
|
|||||||
AC_PREREQ(2.52)
|
AC_PREREQ(2.52)
|
||||||
|
|
||||||
dnl Initialize the automake stuff
|
dnl Initialize the automake stuff
|
||||||
AM_INIT_AUTOMAKE(SimGear, 1.99.5-rc2)
|
AM_INIT_AUTOMAKE(SimGear, 1.9.1)
|
||||||
|
|
||||||
dnl Specify KAI C++ compiler and flags.
|
dnl Specify KAI C++ compiler and flags.
|
||||||
dnl Borrowed with slight modification from blitz distribution.
|
dnl Borrowed with slight modification from blitz distribution.
|
||||||
@@ -37,6 +37,11 @@ AC_PROG_CXX
|
|||||||
AC_PROG_RANLIB
|
AC_PROG_RANLIB
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
AC_PROG_LN_S
|
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
|
dnl set the $host variable based on local machine/os
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
@@ -121,6 +126,12 @@ if test "x$with_plib" != "x" ; then
|
|||||||
EXTRA_DIRS="${EXTRA_DIRS} $with_plib"
|
EXTRA_DIRS="${EXTRA_DIRS} $with_plib"
|
||||||
fi
|
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
|
# specify the osg location
|
||||||
AC_ARG_WITH(osg, [ --with-osg=PREFIX Specify the prefix path to osg])
|
AC_ARG_WITH(osg, [ --with-osg=PREFIX Specify the prefix path to osg])
|
||||||
|
|
||||||
@@ -129,6 +140,21 @@ if test "x$with_osg" != "x" ; then
|
|||||||
EXTRA_DIRS="${EXTRA_DIRS} $with_osg"
|
EXTRA_DIRS="${EXTRA_DIRS} $with_osg"
|
||||||
fi
|
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
|
dnl Determine an extra directories to add to include/lib search paths
|
||||||
case "${host}" in
|
case "${host}" in
|
||||||
*-apple-darwin* | *-*-cygwin* | *-*-mingw32*)
|
*-apple-darwin* | *-*-cygwin* | *-*-mingw32*)
|
||||||
@@ -198,6 +224,7 @@ LIBS=""
|
|||||||
|
|
||||||
dnl check for some default libraries
|
dnl check for some default libraries
|
||||||
AC_SEARCH_LIBS(cos, m)
|
AC_SEARCH_LIBS(cos, m)
|
||||||
|
AC_SEARCH_LIBS(clock_gettime, rt)
|
||||||
|
|
||||||
base_LIBS="$LIBS"
|
base_LIBS="$LIBS"
|
||||||
|
|
||||||
@@ -287,9 +314,54 @@ case "${host}" in
|
|||||||
|
|
||||||
LIBS="$LIBS -framework IOKit -framework OpenAL"
|
LIBS="$LIBS -framework IOKit -framework OpenAL"
|
||||||
openal_LIBS="$LIBS"
|
openal_LIBS="$LIBS"
|
||||||
# not sure how to test if OpenAL exists on MacOS (does it come by default?)
|
|
||||||
OPENAL_OK="yes"
|
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,9 +418,23 @@ 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++
|
# The following are C++ items that need to be tested for with the c++
|
||||||
# compiler
|
# compiler
|
||||||
|
|
||||||
|
CXXCPP="g++ -E"
|
||||||
AC_LANG_PUSH(C++)
|
AC_LANG_PUSH(C++)
|
||||||
|
|
||||||
dnl Check for "plib" without which we cannot go on
|
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)
|
AC_CHECK_HEADER(plib/ul.h)
|
||||||
if test "x$ac_cv_header_plib_ul_h" != "xyes"; then
|
if test "x$ac_cv_header_plib_ul_h" != "xyes"; then
|
||||||
echo
|
echo
|
||||||
@@ -368,8 +454,6 @@ AC_TRY_RUN([
|
|||||||
#define MIN_PLIB_VERSION 185
|
#define MIN_PLIB_VERSION 185
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
int major, minor, micro;
|
|
||||||
|
|
||||||
if ( PLIB_VERSION < MIN_PLIB_VERSION ) {
|
if ( PLIB_VERSION < MIN_PLIB_VERSION ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -386,8 +470,40 @@ int main() {
|
|||||||
|
|
||||||
LIBS="$saved_LIBS"
|
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
|
||||||
|
LDFLAGS="$LDFLAGS -L$with_osg"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
AM_CONDITIONAL(HAVE_FRAMEWORK_OSG, test "x$ac_cv_framework_osg" != "x")
|
||||||
|
|
||||||
AC_CHECK_HEADER(osg/Version)
|
AC_CHECK_HEADER(osg/Version)
|
||||||
if test "x$ac_cv_header_osg_Version" != "xyes"; then
|
if test "x$ac_cv_header_osg_Version" != "xyes"; then
|
||||||
|
if test "x$ac_cv_framework_osg" != "xyes"; then
|
||||||
echo
|
echo
|
||||||
echo "You *must* have the OpenSceneGraph support library installed on your system"
|
echo "You *must* have the OpenSceneGraph support library installed on your system"
|
||||||
echo "to build this version of SimGear!"
|
echo "to build this version of SimGear!"
|
||||||
@@ -396,6 +512,17 @@ if test "x$ac_cv_header_osg_Version" != "xyes"; then
|
|||||||
echo
|
echo
|
||||||
echo "configure aborted."
|
echo "configure aborted."
|
||||||
exit
|
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 "configure aborted."
|
||||||
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_LANG_POP
|
AC_LANG_POP
|
||||||
@@ -465,6 +592,7 @@ AC_CONFIG_FILES([ \
|
|||||||
simgear/props/Makefile \
|
simgear/props/Makefile \
|
||||||
simgear/route/Makefile \
|
simgear/route/Makefile \
|
||||||
simgear/scene/Makefile \
|
simgear/scene/Makefile \
|
||||||
|
simgear/scene/bvh/Makefile \
|
||||||
simgear/scene/material/Makefile \
|
simgear/scene/material/Makefile \
|
||||||
simgear/scene/model/Makefile \
|
simgear/scene/model/Makefile \
|
||||||
simgear/scene/sky/Makefile \
|
simgear/scene/sky/Makefile \
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ Debug
|
|||||||
Release
|
Release
|
||||||
SimGear.ncb
|
SimGear.ncb
|
||||||
SimGear.suo
|
SimGear.suo
|
||||||
|
*.user
|
||||||
|
|||||||
+194
-29
@@ -23,7 +23,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
InlineFunctionExpansion="1"
|
InlineFunctionExpansion="1"
|
||||||
AdditionalIncludeDirectories="..\..;..\..\simgear;..\..\..;..\..\..\install\msvc71\OpenSceneGraph\include;..\..\..\3rdparty\include;"..\..\..\pthreads-w32-2-7-0-release""
|
AdditionalIncludeDirectories="..\..;..\..\simgear;..\..\..\install\msvc71\OpenSceneGraph\include;..\..\..\3rdparty\include;..\..\..\boost_1_36_0"
|
||||||
PreprocessorDefinitions="HAVE_CONFIG_H,NDEBUG,WIN32;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
|
PreprocessorDefinitions="HAVE_CONFIG_H,NDEBUG,WIN32;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
|
||||||
StringPooling="TRUE"
|
StringPooling="TRUE"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="..\..;..\..\simgear;..\..\..;..\..\..\install\msvc71\OpenSceneGraph\include;..\..\..\3rdparty\include;"..\..\..\pthreads-w32-2-7-0-release""
|
AdditionalIncludeDirectories="..\..;..\..\simgear;..\..\..\install\msvc71\OpenSceneGraph\include;..\..\..\3rdparty\include;..\..\..\boost_1_36_0"
|
||||||
PreprocessorDefinitions="HAVE_CONFIG_H,_DEBUG,WIN32;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
|
PreprocessorDefinitions="HAVE_CONFIG_H,_DEBUG,WIN32;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
|
||||||
BasicRuntimeChecks="3"
|
BasicRuntimeChecks="3"
|
||||||
RuntimeLibrary="3"
|
RuntimeLibrary="3"
|
||||||
@@ -287,6 +287,9 @@
|
|||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgmath"
|
Name="Lib_sgmath"
|
||||||
Filter="">
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\math\beziercurve.hxx">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\math\interpolater.cxx">
|
RelativePath="..\..\simgear\math\interpolater.cxx">
|
||||||
</File>
|
</File>
|
||||||
@@ -422,9 +425,6 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\screen\colors.hxx">
|
RelativePath="..\..\simgear\screen\colors.hxx">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\simgear\screen\colours.h">
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\screen\extensions.cxx">
|
RelativePath="..\..\simgear\screen\extensions.cxx">
|
||||||
</File>
|
</File>
|
||||||
@@ -461,12 +461,6 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\screen\shader.h">
|
RelativePath="..\..\simgear\screen\shader.h">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\simgear\screen\texture.cxx">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\simgear\screen\texture.hxx">
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\screen\tr.cxx">
|
RelativePath="..\..\simgear\screen\tr.cxx">
|
||||||
</File>
|
</File>
|
||||||
@@ -649,6 +643,15 @@
|
|||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgprops"
|
Name="Lib_sgprops"
|
||||||
Filter="">
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\props\AtomicChangeListener.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\props\AtomicChangeListener.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\props\ExtendedPropertyAdapter.hxx">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\props\condition.cxx">
|
RelativePath="..\..\simgear\props\condition.cxx">
|
||||||
</File>
|
</File>
|
||||||
@@ -683,12 +686,6 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\model\CheckSceneryVisitor.hxx">
|
RelativePath="..\..\simgear\scene\model\CheckSceneryVisitor.hxx">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\simgear\scene\model\location.cxx">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\simgear\scene\model\location.hxx">
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\model\model.cxx">
|
RelativePath="..\..\simgear\scene\model\model.cxx">
|
||||||
</File>
|
</File>
|
||||||
@@ -725,18 +722,18 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\model\placement.hxx">
|
RelativePath="..\..\simgear\scene\model\placement.hxx">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\simgear\scene\model\placementtrans.cxx">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\simgear\scene\model\placementtrans.hxx">
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\model\SGClipGroup.cxx">
|
RelativePath="..\..\simgear\scene\model\SGClipGroup.cxx">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\model\SGClipGroup.hxx">
|
RelativePath="..\..\simgear\scene\model\SGClipGroup.hxx">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\model\SGInteractionAnimation.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\model\SGInteractionAnimation.hxx">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\model\SGMaterialAnimation.cxx">
|
RelativePath="..\..\simgear\scene\model\SGMaterialAnimation.cxx">
|
||||||
</File>
|
</File>
|
||||||
@@ -811,6 +808,53 @@
|
|||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgmaterial"
|
Name="Lib_sgmaterial"
|
||||||
Filter="">
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\Effect.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\Effect.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\EffectBuilder.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\EffectBuilder.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\EffectCullVisitor.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\EffectCullVisitor.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\EffectGeode.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\EffectGeode.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\GLPredicate.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\GLPredicate.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\Noise.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\Noise.hxx">
|
||||||
|
</File>
|
||||||
|
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\TextureBuilder.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\TextureBuilder.hxx">
|
||||||
|
</File>
|
||||||
|
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\makeEffect.cxx">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\material\mat.cxx">
|
RelativePath="..\..\simgear\scene\material\mat.cxx">
|
||||||
</File>
|
</File>
|
||||||
@@ -829,6 +873,18 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\material\matmodel.hxx">
|
RelativePath="..\..\simgear\scene\material\matmodel.hxx">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\Pass.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\Pass.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\Technique.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\material\Technique.hxx">
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgtgdb"
|
Name="Lib_sgtgdb"
|
||||||
@@ -924,12 +980,6 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\threads\SGQueue.hxx">
|
RelativePath="..\..\simgear\threads\SGQueue.hxx">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\simgear\threads\SGThread.cxx">
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath="..\..\simgear\threads\SGThread.hxx">
|
|
||||||
</File>
|
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgstructure"
|
Name="Lib_sgstructure"
|
||||||
@@ -1130,12 +1180,24 @@
|
|||||||
<Filter
|
<Filter
|
||||||
Name="Lib_sgutil"
|
Name="Lib_sgutil"
|
||||||
Filter="">
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\CopyOp.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\CopyOp.hxx">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\util\NodeAndDrawableVisitor.cxx">
|
RelativePath="..\..\simgear\scene\util\NodeAndDrawableVisitor.cxx">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\util\NodeAndDrawableVisitor.hxx">
|
RelativePath="..\..\simgear\scene\util\NodeAndDrawableVisitor.hxx">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\PrimitiveUtils.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\PrimitiveUtils.hxx">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\util\QuadTreeBuilder.cxx">
|
RelativePath="..\..\simgear\scene\util\QuadTreeBuilder.cxx">
|
||||||
</File>
|
</File>
|
||||||
@@ -1184,12 +1246,115 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\util\SGUpdateVisitor.hxx">
|
RelativePath="..\..\simgear\scene\util\SGUpdateVisitor.hxx">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\SplicingVisitor.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\SplicingVisitor.hxx">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.cxx">
|
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.cxx">
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.hxx">
|
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.hxx">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\util\UpdateOnceCallback.hxx">
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Lib_sgbvh"
|
||||||
|
Filter="">
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHBoundingBoxVisitor.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHDebugCollectVisitor.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHGroup.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHGroup.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHLineGeometry.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHLineGeometry.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHLineSegmentVisitor.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHLineSegmentVisitor.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHMotionTransform.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHMotionTransform.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHNode.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHNode.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticBinary.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticBinary.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticData.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticGeometry.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticGeometry.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticGeometryBuilder.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticLeaf.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticLeaf.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticNode.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticNode.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticTriangle.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHStaticTriangle.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHSubTreeCollector.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHSubTreeCollector.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHTransform.cxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHTransform.hxx">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\simgear\scene\bvh\BVHVisitor.hxx">
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\simgear\simgear_config.h-msvc71">
|
RelativePath="..\..\simgear\simgear_config.h-msvc71">
|
||||||
|
|||||||
@@ -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
+1465
-884
File diff suppressed because it is too large
Load Diff
@@ -106,7 +106,7 @@ void SGBucket::set_bucket( double dlon, double dlat ) {
|
|||||||
} else if ( span <= 1.0 ) {
|
} else if ( span <= 1.0 ) {
|
||||||
x = (int)((dlon - lon) / span);
|
x = (int)((dlon - lon) / span);
|
||||||
} else {
|
} else {
|
||||||
if ( (dlon >= 0) || (fabs(diff) < SG_EPSILON) ) {
|
if ( dlon >= 0 ) {
|
||||||
lon = (int)( (int)(lon / span) * span);
|
lon = (int)( (int)(lon / span) * span);
|
||||||
} else {
|
} else {
|
||||||
// cout << " lon = " << lon
|
// cout << " lon = " << lon
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ static double sg_bucket_span( double l ) {
|
|||||||
class SGBucket {
|
class SGBucket {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double cx, cy; // centerpoint (lon, lat) in degrees of bucket
|
|
||||||
short lon; // longitude index (-180 to 179)
|
short lon; // longitude index (-180 to 179)
|
||||||
short lat; // latitude index (-90 to 89)
|
short lat; // latitude index (-90 to 89)
|
||||||
char x; // x subdivision (0 to 7)
|
char x; // x subdivision (0 to 7)
|
||||||
|
|||||||
+27
-1
@@ -131,9 +131,35 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# if ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 3 )
|
||||||
inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
|
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
|
||||||
|
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
# define isnan(x) _isnan(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -118,10 +118,10 @@
|
|||||||
/** Nautical Miles to Radians */
|
/** Nautical Miles to Radians */
|
||||||
#define SG_RAD_TO_NM 3437.7467707849392526
|
#define SG_RAD_TO_NM 3437.7467707849392526
|
||||||
|
|
||||||
/** Miles per second to Knots */
|
/** meters per second to Knots */
|
||||||
#define SG_MPS_TO_KT 1.9438444924406046432
|
#define SG_MPS_TO_KT 1.9438444924406046432
|
||||||
|
|
||||||
/** Knots to Miles per second */
|
/** Knots to meters per second */
|
||||||
#define SG_KT_TO_MPS 0.5144444444444444444
|
#define SG_KT_TO_MPS 0.5144444444444444444
|
||||||
|
|
||||||
/** Feet per second to Knots */
|
/** Feet per second to Knots */
|
||||||
@@ -130,16 +130,16 @@
|
|||||||
/** Knots to Feet per second */
|
/** Knots to Feet per second */
|
||||||
#define SG_KT_TO_FPS 1.6878098571011956874
|
#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
|
#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
|
#define SG_MPH_TO_MPS 0.44704
|
||||||
|
|
||||||
/** Meters per second to Kilometers per hour */
|
/** Meters per second to Kilometers per hour */
|
||||||
#define SG_MPS_TO_KMH 3.6
|
#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
|
#define SG_KMH_TO_MPS 0.2777777777777777778
|
||||||
|
|
||||||
/** Pascal to Inch Mercury */
|
/** Pascal to Inch Mercury */
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include <simgear/debug/debug_types.h>
|
#include <simgear/debug/debug_types.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "Debug/logstream.hxx"
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
class Test {
|
class Test {
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
#include <simgear/math/sg_geodesy.hxx>
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
#include <simgear/math/point3d.hxx>
|
#include <simgear/math/point3d.hxx>
|
||||||
#include <simgear/math/polar3d.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/cloudfield.hxx>
|
||||||
#include <simgear/scene/sky/newcloud.hxx>
|
#include <simgear/scene/sky/newcloud.hxx>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
@@ -175,7 +175,7 @@ SGEnviro::SGEnviro() :
|
|||||||
lightning_enable_state(false),
|
lightning_enable_state(false),
|
||||||
elapsed_time(0.0),
|
elapsed_time(0.0),
|
||||||
dt(0.0),
|
dt(0.0),
|
||||||
soundMgr(NULL),
|
sampleGroup(NULL),
|
||||||
snd_active(false),
|
snd_active(false),
|
||||||
snd_dist(0.0),
|
snd_dist(0.0),
|
||||||
min_time_before_lt(0.0),
|
min_time_before_lt(0.0),
|
||||||
@@ -189,6 +189,8 @@ SGEnviro::SGEnviro() :
|
|||||||
}
|
}
|
||||||
|
|
||||||
SGEnviro::~SGEnviro(void) {
|
SGEnviro::~SGEnviro(void) {
|
||||||
|
if (sampleGroup) delete sampleGroup;
|
||||||
|
|
||||||
// OSGFIXME
|
// OSGFIXME
|
||||||
return;
|
return;
|
||||||
list_of_lightning::iterator iLightning;
|
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) {
|
void SGEnviro::set_sampleGroup(SGSampleGroup *sgr) {
|
||||||
soundMgr = mgr;
|
sampleGroup = sgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SGEnviro::drawPrecipitation(double rain_norm, double snow_norm, double hail_norm, double pitch, double roll, double heading, double hspeed) {
|
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[PY] = alt;
|
||||||
top[PZ] = 0;
|
top[PZ] = 0;
|
||||||
lt_build_tree_branch(0, top, 1.0, 50, top[PY] / 8.0);
|
lt_build_tree_branch(0, top, 1.0, 50, top[PY] / 8.0);
|
||||||
if( ! sgEnviro.soundMgr )
|
if( ! sgEnviro.sampleGroup )
|
||||||
return;
|
return;
|
||||||
Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 );
|
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 );
|
Point3D dest( lon*SG_DEGREES_TO_RADIANS, lat*SG_DEGREES_TO_RADIANS, 0.0 );
|
||||||
@@ -737,7 +739,7 @@ void SGEnviro::drawLightning(void) {
|
|||||||
return;
|
return;
|
||||||
list_of_lightning::iterator iLightning;
|
list_of_lightning::iterator iLightning;
|
||||||
// play 'thunder' for lightning
|
// play 'thunder' for lightning
|
||||||
if( snd_active )
|
if( snd_active ) {
|
||||||
if( !snd_playing ) {
|
if( !snd_playing ) {
|
||||||
// wait until sound has reached us
|
// wait until sound has reached us
|
||||||
snd_timer += dt;
|
snd_timer += dt;
|
||||||
@@ -751,20 +753,21 @@ void SGEnviro::drawLightning(void) {
|
|||||||
double ax = 0.0, ay = 0.0;
|
double ax = 0.0, ay = 0.0;
|
||||||
ax = cos(course) * dist;
|
ax = cos(course) * dist;
|
||||||
ay = sin(course) * dist;
|
ay = sin(course) * dist;
|
||||||
SGSharedPtr<SGSoundSample> snd = soundMgr->find("thunder");
|
SGSharedPtr<SGSoundSample> snd = sampleGroup->find("thunder");
|
||||||
if( snd ) {
|
if( snd ) {
|
||||||
ALfloat pos[3]={ax, ay, -sgEnviro.last_alt };
|
SGVec3d pos = SGVec3d(ax, ay, -sgEnviro.last_alt);
|
||||||
snd->set_source_pos(pos);
|
snd->set_position(pos);
|
||||||
snd->play_once();
|
snd->play_once();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if( !soundMgr->is_playing("thunder") ) {
|
if( !sampleGroup->is_playing("thunder") ) {
|
||||||
snd_active = false;
|
snd_active = false;
|
||||||
snd_playing = false;
|
snd_playing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if( ! lightning_enable_state )
|
if( ! lightning_enable_state )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ using std::vector;
|
|||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
class SGLightning;
|
class SGLightning;
|
||||||
class SGSoundMgr;
|
class SGSampleGroup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulate some echo on a weather radar.
|
* Simulate some echo on a weather radar.
|
||||||
@@ -84,7 +84,7 @@ private:
|
|||||||
sgVec4 fog_color;
|
sgVec4 fog_color;
|
||||||
sgMat4 transform;
|
sgMat4 transform;
|
||||||
double last_lon, last_lat, last_alt;
|
double last_lon, last_lat, last_alt;
|
||||||
SGSoundMgr *soundMgr;
|
SGSampleGroup *sampleGroup;
|
||||||
bool snd_active, snd_playing;
|
bool snd_active, snd_playing;
|
||||||
double snd_timer, snd_wait, snd_pos_lat, snd_pos_lon, snd_dist;
|
double snd_timer, snd_wait, snd_pos_lat, snd_pos_lon, snd_dist;
|
||||||
double min_time_before_lt;
|
double min_time_before_lt;
|
||||||
@@ -243,7 +243,7 @@ public:
|
|||||||
* Forward the sound manager instance to be able to play samples.
|
* Forward the sound manager instance to be able to play samples.
|
||||||
* @param mgr a running sound manager
|
* @param mgr a running sound manager
|
||||||
*/
|
*/
|
||||||
void set_soundMgr(SGSoundMgr *mgr);
|
void set_sampleGroup(SGSampleGroup *sgr);
|
||||||
|
|
||||||
void setFOV( float w, float h );
|
void setFOV( float w, float h );
|
||||||
void getFOV( float &w, float &h );
|
void getFOV( float &w, float &h );
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ public:
|
|||||||
* @return planets array
|
* @return planets array
|
||||||
*/
|
*/
|
||||||
inline SGVec3d *getPlanets() { return planets; }
|
inline SGVec3d *getPlanets() { return planets; }
|
||||||
|
inline const SGVec3d *getPlanets() const { return planets; }
|
||||||
|
|
||||||
/** @return the numbers of defined stars. */
|
/** @return the numbers of defined stars. */
|
||||||
inline int getNumStars() const { return stars->getNumStars(); }
|
inline int getNumStars() const { return stars->getNumStars(); }
|
||||||
@@ -170,6 +171,7 @@ public:
|
|||||||
* @returns star array
|
* @returns star array
|
||||||
*/
|
*/
|
||||||
inline SGVec3d *getStars() { return stars->getStars(); }
|
inline SGVec3d *getStars() { return stars->getStars(); }
|
||||||
|
inline const SGVec3d *getStars() const { return stars->getStars(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+21
-3
@@ -26,34 +26,52 @@ noinst_PROGRAMS = decode_binobj socktest lowtest tcp_server tcp_client
|
|||||||
|
|
||||||
tcp_server_SOURCES = tcp_server.cxx
|
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 = \
|
tcp_server_LDADD = \
|
||||||
libsgio.a \
|
libsgio.a \
|
||||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||||
-lplibnet -lplibul -lz \
|
$(tcp_server_PLIB_LIBS) -lz \
|
||||||
$(network_LIBS) \
|
$(network_LIBS) \
|
||||||
$(base_LIBS)
|
$(base_LIBS)
|
||||||
|
|
||||||
tcp_client_SOURCES = tcp_client.cxx
|
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 = \
|
tcp_client_LDADD = \
|
||||||
libsgio.a \
|
libsgio.a \
|
||||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||||
-lplibnet -lplibul -lz \
|
$(tcp_client_PLIB_LIBS) -lz \
|
||||||
$(network_LIBS) \
|
$(network_LIBS) \
|
||||||
$(base_LIBS)
|
$(base_LIBS)
|
||||||
|
|
||||||
socktest_SOURCES = socktest.cxx
|
socktest_SOURCES = socktest.cxx
|
||||||
|
|
||||||
|
if HAVE_FRAMEWORK_PLIB
|
||||||
|
socktest_LDFLAGS = $(plib_FRAMEWORK)
|
||||||
|
else
|
||||||
|
socktest_PLIB_LIBS = -lplibnet -lplibul
|
||||||
|
endif
|
||||||
|
|
||||||
socktest_LDADD = \
|
socktest_LDADD = \
|
||||||
libsgio.a \
|
libsgio.a \
|
||||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||||
-lplibnet -lplibul -lz \
|
$(socktest_PLIB_LIBS) -lz
|
||||||
$(network_LIBS) \
|
$(network_LIBS) \
|
||||||
$(base_LIBS)
|
$(base_LIBS)
|
||||||
|
|
||||||
|
|||||||
+16
-8
@@ -55,21 +55,25 @@ void sgWriteChar ( gzFile fd, const char var )
|
|||||||
|
|
||||||
void sgReadFloat ( gzFile fd, float *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 ;
|
read_error = true ;
|
||||||
}
|
}
|
||||||
if ( sgIsBigEndian() ) {
|
if ( sgIsBigEndian() ) {
|
||||||
sgEndianSwap( (uint32_t *)var);
|
sgEndianSwap( &buf.u );
|
||||||
}
|
}
|
||||||
|
*var = buf.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sgWriteFloat ( gzFile fd, const float var )
|
void sgWriteFloat ( gzFile fd, const float var )
|
||||||
{
|
{
|
||||||
|
union { float v; uint32_t u; } buf;
|
||||||
|
buf.v = var;
|
||||||
if ( sgIsBigEndian() ) {
|
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 ;
|
write_error = true ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,21 +81,25 @@ void sgWriteFloat ( gzFile fd, const float var )
|
|||||||
|
|
||||||
void sgReadDouble ( gzFile fd, double *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 ;
|
read_error = true ;
|
||||||
}
|
}
|
||||||
if ( sgIsBigEndian() ) {
|
if ( sgIsBigEndian() ) {
|
||||||
sgEndianSwap( (uint64_t *)var);
|
sgEndianSwap( &buf.u );
|
||||||
}
|
}
|
||||||
|
*var = buf.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sgWriteDouble ( gzFile fd, const double var )
|
void sgWriteDouble ( gzFile fd, const double var )
|
||||||
{
|
{
|
||||||
|
union { double v; uint64_t u; } buf;
|
||||||
|
buf.v = var;
|
||||||
if ( sgIsBigEndian() ) {
|
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 ;
|
write_error = true ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#include <simgear/math/sg_types.hxx>
|
#include <simgear/math/sg_types.hxx>
|
||||||
|
#include <simgear/math/point3d.hxx>
|
||||||
#include <simgear/bucket/newbucket.hxx>
|
#include <simgear/bucket/newbucket.hxx>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class TcpServer
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TcpServer();
|
TcpServer();
|
||||||
|
~TcpServer();
|
||||||
bool open();
|
bool open();
|
||||||
bool process();
|
bool process();
|
||||||
bool close();
|
bool close();
|
||||||
@@ -25,6 +26,11 @@ TcpServer::TcpServer()
|
|||||||
channel = new SGSocket( "", "5500", "tcp" );
|
channel = new SGSocket( "", "5500", "tcp" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TcpServer::~TcpServer()
|
||||||
|
{
|
||||||
|
delete channel;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TcpServer::open()
|
TcpServer::open()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,11 +2,9 @@ includedir = @includedir@/magvar
|
|||||||
|
|
||||||
lib_LIBRARIES = libsgmagvar.a
|
lib_LIBRARIES = libsgmagvar.a
|
||||||
|
|
||||||
include_HEADERS = magvar.hxx
|
include_HEADERS = magvar.hxx coremag.hxx
|
||||||
|
|
||||||
libsgmagvar_a_SOURCES = \
|
libsgmagvar_a_SOURCES = coremag.cxx magvar.cxx
|
||||||
coremag.hxx coremag.cxx \
|
|
||||||
magvar.cxx
|
|
||||||
|
|
||||||
noinst_PROGRAMS = testmagvar
|
noinst_PROGRAMS = testmagvar
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ check_PROGRAMS = SGMathTest SGGeometryTest
|
|||||||
TESTS = $(check_PROGRAMS)
|
TESTS = $(check_PROGRAMS)
|
||||||
|
|
||||||
SGMathTest_SOURCES = SGMathTest.cxx
|
SGMathTest_SOURCES = SGMathTest.cxx
|
||||||
SGMathTest_LDADD = libsgmath.a $(base_LIBS)
|
SGMathTest_LDADD = libsgmath.a -lsgstructure $(base_LIBS)
|
||||||
|
|
||||||
SGGeometryTest_SOURCES = SGGeometryTest.cxx
|
SGGeometryTest_SOURCES = SGGeometryTest.cxx
|
||||||
SGGeometryTest_LDADD = libsgmath.a $(base_LIBS)
|
SGGeometryTest_LDADD = libsgmath.a -lsgstructure $(base_LIBS)
|
||||||
|
|
||||||
lib_LIBRARIES = libsgmath.a
|
lib_LIBRARIES = libsgmath.a
|
||||||
|
|
||||||
@@ -42,7 +42,8 @@ include_HEADERS = \
|
|||||||
SGTriangle.hxx \
|
SGTriangle.hxx \
|
||||||
SGVec2.hxx \
|
SGVec2.hxx \
|
||||||
SGVec3.hxx \
|
SGVec3.hxx \
|
||||||
SGVec4.hxx
|
SGVec4.hxx \
|
||||||
|
beziercurve.hxx
|
||||||
|
|
||||||
libsgmath_a_SOURCES = \
|
libsgmath_a_SOURCES = \
|
||||||
interpolater.cxx \
|
interpolater.cxx \
|
||||||
|
|||||||
+52
-1
@@ -25,6 +25,20 @@ public:
|
|||||||
_min(SGLimits<T>::max(), SGLimits<T>::max(), SGLimits<T>::max()),
|
_min(SGLimits<T>::max(), SGLimits<T>::max(), SGLimits<T>::max()),
|
||||||
_max(-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)
|
void setMin(const SGVec3<T>& min)
|
||||||
{ _min = min; }
|
{ _min = min; }
|
||||||
const SGVec3<T>& getMin() const
|
const SGVec3<T>& getMin() const
|
||||||
@@ -35,6 +49,29 @@ public:
|
|||||||
const SGVec3<T>& getMax() const
|
const SGVec3<T>& getMax() const
|
||||||
{ return _max; }
|
{ 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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Only works for floating point types
|
// Only works for floating point types
|
||||||
SGVec3<T> getCenter() const
|
SGVec3<T> getCenter() const
|
||||||
{ return T(0.5)*(_min + _max); }
|
{ return T(0.5)*(_min + _max); }
|
||||||
@@ -42,6 +79,8 @@ public:
|
|||||||
// Only valid for nonempty boxes
|
// Only valid for nonempty boxes
|
||||||
SGVec3<T> getSize() const
|
SGVec3<T> getSize() const
|
||||||
{ return _max - _min; }
|
{ return _max - _min; }
|
||||||
|
SGVec3<T> getHalfSize() const
|
||||||
|
{ return T(0.5)*getSize(); }
|
||||||
|
|
||||||
T getVolume() const
|
T getVolume() const
|
||||||
{
|
{
|
||||||
@@ -83,7 +122,7 @@ public:
|
|||||||
// Note that this only works if the box is nonmepty
|
// Note that this only works if the box is nonmepty
|
||||||
unsigned getBroadestAxis() const
|
unsigned getBroadestAxis() const
|
||||||
{
|
{
|
||||||
SGVec3d size = getSize();
|
SGVec3<T> size = getSize();
|
||||||
if (size[1] <= size[0] && size[2] <= size[0])
|
if (size[1] <= size[0] && size[2] <= size[0])
|
||||||
return 0;
|
return 0;
|
||||||
else if (size[2] <= size[1])
|
else if (size[2] <= size[1])
|
||||||
@@ -92,6 +131,18 @@ public:
|
|||||||
return 2;
|
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:
|
private:
|
||||||
SGVec3<T> _min;
|
SGVec3<T> _min;
|
||||||
SGVec3<T> _max;
|
SGVec3<T> _max;
|
||||||
|
|||||||
+11
-7
@@ -17,22 +17,24 @@
|
|||||||
|
|
||||||
#include "SGMath.hxx"
|
#include "SGMath.hxx"
|
||||||
|
|
||||||
osg::Matrix SGGeod::makeSimulationFrameRelative()
|
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||||
|
|
||||||
|
osg::Matrix SGGeod::makeSimulationFrameRelative() const
|
||||||
{
|
{
|
||||||
SGQuatd hlOr = SGQuatd::fromLonLat(*this);
|
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());
|
osg::Matrix result(makeSimulationFrameRelative());
|
||||||
SGVec3d coord;
|
SGVec3d coord;
|
||||||
SGGeodesy::SGGeodToCart(*this, coord);
|
SGGeodesy::SGGeodToCart(*this, coord);
|
||||||
result.setTrans(coord.osg());
|
result.setTrans(toOsg(coord));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Matrix SGGeod::makeZUpFrameRelative()
|
osg::Matrix SGGeod::makeZUpFrameRelative() const
|
||||||
{
|
{
|
||||||
osg::Matrix result(makeSimulationFrameRelative());
|
osg::Matrix result(makeSimulationFrameRelative());
|
||||||
// 180 degree rotation around Y axis
|
// 180 degree rotation around Y axis
|
||||||
@@ -41,11 +43,13 @@ osg::Matrix SGGeod::makeZUpFrameRelative()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Matrix SGGeod::makeZUpFrame()
|
osg::Matrix SGGeod::makeZUpFrame() const
|
||||||
{
|
{
|
||||||
osg::Matrix result(makeZUpFrameRelative());
|
osg::Matrix result(makeZUpFrameRelative());
|
||||||
SGVec3d coord;
|
SGVec3d coord;
|
||||||
SGGeodesy::SGGeodToCart(*this, coord);
|
SGGeodesy::SGGeodToCart(*this, coord);
|
||||||
result.setTrans(coord.osg());
|
result.setTrans(toOsg(coord));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
+28
-6
@@ -20,7 +20,9 @@
|
|||||||
|
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
|
|
||||||
|
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||||
#include <osg/Matrix>
|
#include <osg/Matrix>
|
||||||
|
#endif
|
||||||
|
|
||||||
// #define SG_GEOD_NATIVE_DEGREE
|
// #define SG_GEOD_NATIVE_DEGREE
|
||||||
|
|
||||||
@@ -42,6 +44,10 @@ public:
|
|||||||
static SGGeod fromRadM(double lon, double lat, double elevation);
|
static SGGeod fromRadM(double lon, double lat, double elevation);
|
||||||
/// Factory from angular values in degrees and elevation in m
|
/// Factory from angular values in degrees and elevation in m
|
||||||
static SGGeod fromDegM(double lon, double lat, double elevation);
|
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
|
/// Factory to convert position from a cartesian position assumed to be
|
||||||
/// in wgs84 measured in meters
|
/// in wgs84 measured in meters
|
||||||
/// Note that this conversion is relatively expensive to compute
|
/// Note that this conversion is relatively expensive to compute
|
||||||
@@ -80,25 +86,27 @@ public:
|
|||||||
/// Set the geodetic elevation from the argument given in feet
|
/// Set the geodetic elevation from the argument given in feet
|
||||||
void setElevationFt(double elevation);
|
void setElevationFt(double elevation);
|
||||||
|
|
||||||
|
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||||
// Create a local coordinate frame in the earth-centered frame of
|
// Create a local coordinate frame in the earth-centered frame of
|
||||||
// reference. X points north, Z points down.
|
// reference. X points north, Z points down.
|
||||||
// makeSimulationFrameRelative() only includes rotation.
|
// makeSimulationFrameRelative() only includes rotation.
|
||||||
|
osg::Matrix makeSimulationFrameRelative() const;
|
||||||
osg::Matrix makeSimulationFrameRelative();
|
osg::Matrix makeSimulationFrame() const;
|
||||||
osg::Matrix makeSimulationFrame();
|
|
||||||
|
|
||||||
// Create a Z-up local coordinate frame in the earth-centered frame
|
// Create a Z-up local coordinate frame in the earth-centered frame
|
||||||
// of reference. This is what scenery models, etc. expect.
|
// of reference. This is what scenery models, etc. expect.
|
||||||
// makeZUpFrameRelative() only includes rotation.
|
// makeZUpFrameRelative() only includes rotation.
|
||||||
osg::Matrix makeZUpFrameRelative();
|
osg::Matrix makeZUpFrameRelative() const;
|
||||||
osg::Matrix makeZUpFrame();
|
osg::Matrix makeZUpFrame() const;
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
/// This one is private since construction is not unique if you do
|
/// This one is private since construction is not unique if you do
|
||||||
/// not know the units of the arguments. Use the factory methods for
|
/// not know the units of the arguments. Use the factory methods for
|
||||||
/// that purpose
|
/// that purpose
|
||||||
SGGeod(double lon, double lat, double elevation);
|
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
|
/// 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.
|
/// 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
|
/// The places where it makes sense to use radians is when we convert
|
||||||
@@ -192,6 +200,20 @@ SGGeod::fromDegM(double lon, double lat, double elevation)
|
|||||||
#endif
|
#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
|
inline
|
||||||
SGGeod
|
SGGeod
|
||||||
SGGeod::fromCart(const SGVec3<double>& cart)
|
SGGeod::fromCart(const SGVec3<double>& cart)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <simgear/structure/exception.hxx>
|
||||||
#include "SGMath.hxx"
|
#include "SGMath.hxx"
|
||||||
|
|
||||||
// These are hard numbers from the WGS84 standard. DON'T MODIFY
|
// 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)
|
#define E2 fabs(1 - _SQUASH*_SQUASH)
|
||||||
static double a = _EQURAD;
|
static double a = _EQURAD;
|
||||||
static double ra2 = 1/(_EQURAD*_EQURAD);
|
static double ra2 = 1/(_EQURAD*_EQURAD);
|
||||||
static double e = sqrt(E2);
|
//static double e = sqrt(E2);
|
||||||
static double e2 = E2;
|
static double e2 = E2;
|
||||||
static double e4 = E2*E2;
|
static double e4 = E2*E2;
|
||||||
|
|
||||||
@@ -78,11 +79,30 @@ SGGeodesy::SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod)
|
|||||||
double Y = cart(1);
|
double Y = cart(1);
|
||||||
double Z = cart(2);
|
double Z = cart(2);
|
||||||
double XXpYY = X*X+Y*Y;
|
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 sqrtXXpYY = sqrt(XXpYY);
|
||||||
double p = XXpYY*ra2;
|
double p = XXpYY*ra2;
|
||||||
double q = Z*Z*(1-e2)*ra2;
|
double q = Z*Z*(1-e2)*ra2;
|
||||||
double r = 1/6.0*(p+q-e4);
|
double r = 1/6.0*(p+q-e4);
|
||||||
double s = e4*p*q/(4*r*r*r);
|
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 t = pow(1+s+sqrt(s*(2+s)), 1/3.0);
|
||||||
double u = r*(1+t+1/t);
|
double u = r*(1+t+1/t);
|
||||||
double v = sqrt(u*u+e4*q);
|
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);
|
double sinphi2 = sin(phi2), cosphi2 = cos(phi2);
|
||||||
|
|
||||||
if( (fabs(lat1-lat2) < testv &&
|
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 */
|
// TWO STATIONS ARE IDENTICAL : SET DISTANCE & AZIMUTHS TO ZERO */
|
||||||
*az1 = 0.0; *az2 = 0.0; *s = 0.0;
|
*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;
|
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
|
/// Geocentric routines
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -486,7 +540,7 @@ SGGeodesy::courseRad(const SGGeoc& from, const SGGeoc& to)
|
|||||||
}
|
}
|
||||||
|
|
||||||
double
|
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 +
|
// d = 2*asin(sqrt((sin((lat1-lat2)/2))^2 +
|
||||||
// cos(lat1)*cos(lat2)*(sin((lon1-lon2)/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 tmp2 = sin(0.5*(from.getLongitudeRad() - to.getLongitudeRad()));
|
||||||
double square = tmp1*tmp1 + cosLatFrom*cosLatTo*tmp2*tmp2;
|
double square = tmp1*tmp1 + cosLatFrom*cosLatTo*tmp2*tmp2;
|
||||||
double s = SGMiscd::min(sqrt(SGMiscd::max(square, 0)), 1);
|
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,
|
static bool inverse(const SGGeod& p1, const SGGeod& p2, double& course1,
|
||||||
double& course2, double& distance);
|
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
|
// Geocentric course/distance computation
|
||||||
static void advanceRadM(const SGGeoc& geoc, double course, double distance,
|
static void advanceRadM(const SGGeoc& geoc, double course, double distance,
|
||||||
SGGeoc& result);
|
SGGeoc& result);
|
||||||
static double courseRad(const SGGeoc& from, const SGGeoc& to);
|
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);
|
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());
|
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>
|
template<typename T>
|
||||||
bool
|
bool
|
||||||
TriangleLineIntersectionTest(void)
|
TriangleLineIntersectionTest(void)
|
||||||
@@ -44,6 +140,8 @@ TriangleLineIntersectionTest(void)
|
|||||||
|
|
||||||
SGTriangle<T> tri(v0, v1, v2);
|
SGTriangle<T> tri(v0, v1, v2);
|
||||||
|
|
||||||
|
T triangleEps = 100*SGLimits<T>::epsilon();
|
||||||
|
|
||||||
// generate random coeficients
|
// generate random coeficients
|
||||||
T u = 4*sg_random() - 2;
|
T u = 4*sg_random() - 2;
|
||||||
T v = 4*sg_random() - 2;
|
T v = 4*sg_random() - 2;
|
||||||
@@ -59,7 +157,7 @@ TriangleLineIntersectionTest(void)
|
|||||||
|
|
||||||
if (intersects(isectres, tri, lineSegment)) {
|
if (intersects(isectres, tri, lineSegment)) {
|
||||||
if (0 <= u && 0 <= v && u+v <= 1 && 0 <= t && t <= 1) {
|
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
|
std::cout << "Failed line segment intersection test #" << i
|
||||||
<< ": not equivalent!\nu = "
|
<< ": not equivalent!\nu = "
|
||||||
<< u << ", v = " << v << ", t = " << t
|
<< u << ", v = " << v << ", t = " << t
|
||||||
@@ -87,7 +185,7 @@ TriangleLineIntersectionTest(void)
|
|||||||
ray.set(isectpt - t*dir, dir);
|
ray.set(isectpt - t*dir, dir);
|
||||||
if (intersects(isectres, tri, ray)) {
|
if (intersects(isectres, tri, ray)) {
|
||||||
if (0 <= u && 0 <= v && u+v <= 1 && 0 <= t) {
|
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
|
std::cout << "Failed ray intersection test #" << i
|
||||||
<< ": not equivalent!\nu = "
|
<< ": not equivalent!\nu = "
|
||||||
<< u << ", v = " << v << ", t = " << t
|
<< u << ", v = " << v << ", t = " << t
|
||||||
@@ -422,6 +520,13 @@ main(void)
|
|||||||
<< "Some of these tests can fail due to roundoff problems...\n"
|
<< "Some of these tests can fail due to roundoff problems...\n"
|
||||||
<< "Dont worry if only a few of them fail..." << std::endl;
|
<< "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>())
|
if (!TriangleLineIntersectionTest<float>())
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
if (!TriangleLineIntersectionTest<double>())
|
if (!TriangleLineIntersectionTest<double>())
|
||||||
|
|||||||
+461
-11
@@ -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
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -20,7 +20,21 @@
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool
|
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())
|
if (sphere.empty())
|
||||||
return false;
|
return false;
|
||||||
@@ -45,15 +59,15 @@ intersects(const SGBox<T>& box, const SGSphere<T>& sphere)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// make it symmetric
|
// make it symmetric
|
||||||
template<typename T>
|
template<typename T1, typename T2>
|
||||||
inline bool
|
inline bool
|
||||||
intersects(const SGSphere<T>& sphere, const SGBox<T>& box)
|
intersects(const SGSphere<T1>& sphere, const SGBox<T2>& box)
|
||||||
{ return intersects(box, sphere); }
|
{ return intersects(box, sphere); }
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T1, typename T2>
|
||||||
inline bool
|
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])
|
if (v[0] < box.getMin()[0])
|
||||||
return false;
|
return false;
|
||||||
@@ -69,9 +83,9 @@ intersects(const SGVec3<T>& v, const SGBox<T>& box)
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T1, typename T2>
|
||||||
inline bool
|
inline bool
|
||||||
intersects(const SGBox<T>& box, const SGVec3<T>& v)
|
intersects(const SGBox<T1>& box, const SGVec3<T2>& v)
|
||||||
{ return intersects(v, box); }
|
{ return intersects(v, box); }
|
||||||
|
|
||||||
|
|
||||||
@@ -529,13 +543,427 @@ template<typename T>
|
|||||||
inline bool
|
inline bool
|
||||||
intersects(const SGTriangle<T>& tri, const SGLineSegment<T>& lineSegment, T eps = 0)
|
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
|
// well optimized, implement that special case
|
||||||
SGVec3<T> dummy;
|
SGVec3<T> dummy;
|
||||||
return intersects(dummy, tri, lineSegment, eps);
|
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>
|
template<typename T>
|
||||||
inline bool
|
inline bool
|
||||||
intersects(const SGVec3<T>& v, const SGSphere<T>& sphere)
|
intersects(const SGVec3<T>& v, const SGSphere<T>& sphere)
|
||||||
@@ -557,9 +985,9 @@ intersects(const SGBox<T>& box, const SGLineSegment<T>& lineSegment)
|
|||||||
// See Tomas Akeniene - Moeller/Eric Haines: Real Time Rendering
|
// See Tomas Akeniene - Moeller/Eric Haines: Real Time Rendering
|
||||||
|
|
||||||
SGVec3<T> c = lineSegment.getCenter() - box.getCenter();
|
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> 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])
|
if (fabs(c[0]) > v[0] + h[0])
|
||||||
return false;
|
return false;
|
||||||
@@ -624,4 +1052,26 @@ inline bool
|
|||||||
intersects(const SGRay<T>& ray, const SGBox<T>& box)
|
intersects(const SGRay<T>& ray, const SGBox<T>& box)
|
||||||
{ return intersects(box, ray); }
|
{ 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
|
#endif
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ public:
|
|||||||
_start(start),
|
_start(start),
|
||||||
_direction(end - 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)
|
void set(const SGVec3<T>& start, const SGVec3<T>& end)
|
||||||
{ _start = start; _direction = end - start; }
|
{ _start = start; _direction = end - start; }
|
||||||
@@ -43,6 +48,14 @@ public:
|
|||||||
SGVec3<T> getCenter() const
|
SGVec3<T> getCenter() const
|
||||||
{ return _start + T(0.5)*_direction; }
|
{ 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:
|
private:
|
||||||
SGVec3<T> _start;
|
SGVec3<T> _start;
|
||||||
SGVec3<T> _direction;
|
SGVec3<T> _direction;
|
||||||
|
|||||||
@@ -174,16 +174,22 @@ MatrixTest(void)
|
|||||||
// Create some test matrix
|
// Create some test matrix
|
||||||
SGVec3<T> v0(2, 7, 17);
|
SGVec3<T> v0(2, 7, 17);
|
||||||
SGQuat<T> q0 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), normalize(v0));
|
SGQuat<T> q0 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), normalize(v0));
|
||||||
SGMatrix<T> m0;
|
SGMatrix<T> m0 = SGMatrix<T>::unit();
|
||||||
m0.postMultTranslate(v0);
|
m0.postMultTranslate(v0);
|
||||||
m0.postMultRotate(q0);
|
m0.postMultRotate(q0);
|
||||||
|
|
||||||
// Check the tqo forms of the inverse for that kind of special matrix
|
// Check the three forms of the inverse for that kind of special matrix
|
||||||
SGMatrix<T> m1, m2;
|
SGMatrix<T> m1 = SGMatrix<T>::unit();
|
||||||
invert(m1, m0);
|
m1.preMultTranslate(-v0);
|
||||||
m2 = transNeg(m0);
|
m1.preMultRotate(inverse(q0));
|
||||||
|
|
||||||
|
SGMatrix<T> m2, m3;
|
||||||
|
invert(m2, m0);
|
||||||
|
m3 = transNeg(m0);
|
||||||
if (!equivalent(m1, m2))
|
if (!equivalent(m1, m2))
|
||||||
return false;
|
return false;
|
||||||
|
if (!equivalent(m2, m3))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Check matrix multiplication and inversion
|
// Check matrix multiplication and inversion
|
||||||
if (!equivalent(m0*m1, SGMatrix<T>::unit()))
|
if (!equivalent(m0*m1, SGMatrix<T>::unit()))
|
||||||
@@ -194,6 +200,10 @@ MatrixTest(void)
|
|||||||
return false;
|
return false;
|
||||||
if (!equivalent(m2*m0, SGMatrix<T>::unit()))
|
if (!equivalent(m2*m0, SGMatrix<T>::unit()))
|
||||||
return false;
|
return false;
|
||||||
|
if (!equivalent(m0*m3, SGMatrix<T>::unit()))
|
||||||
|
return false;
|
||||||
|
if (!equivalent(m3*m0, SGMatrix<T>::unit()))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -202,10 +212,10 @@ bool
|
|||||||
GeodesyTest(void)
|
GeodesyTest(void)
|
||||||
{
|
{
|
||||||
// We know that the values are on the order of 1
|
// 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
|
// For the altitude values we need to tolerate relative errors in the order
|
||||||
// of the radius
|
// of the radius
|
||||||
double epsM = 1e6*SGLimits<double>::epsilon();
|
double epsM = 10*6e6*SGLimits<double>::epsilon();
|
||||||
|
|
||||||
SGVec3<double> cart0, cart1;
|
SGVec3<double> cart0, cart1;
|
||||||
SGGeod geod0, geod1;
|
SGGeod geod0, geod1;
|
||||||
|
|||||||
@@ -184,8 +184,15 @@ public:
|
|||||||
template<typename S>
|
template<typename S>
|
||||||
SGMatrix& preMultTranslate(const SGVec3<S>& t)
|
SGMatrix& preMultTranslate(const SGVec3<S>& t)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < SGMatrix<T>::nCols-1; ++i)
|
for (unsigned i = 0; i < 3; ++i) {
|
||||||
(*this)(i,3) += T(t(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;
|
return *this;
|
||||||
}
|
}
|
||||||
template<typename S>
|
template<typename S>
|
||||||
@@ -193,7 +200,7 @@ public:
|
|||||||
{
|
{
|
||||||
SGVec4<T> col3((*this)(0,3), (*this)(1,3), (*this)(2,3), (*this)(3,3));
|
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) {
|
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;
|
col3 += T(t(i))*tmp;
|
||||||
}
|
}
|
||||||
(*this)(0,3) = col3(0); (*this)(1,3) = col3(1);
|
(*this)(0,3) = col3(0); (*this)(1,3) = col3(1);
|
||||||
|
|||||||
@@ -23,14 +23,25 @@ class SGPlane {
|
|||||||
public:
|
public:
|
||||||
SGPlane()
|
SGPlane()
|
||||||
{ }
|
{ }
|
||||||
SGPlane(const SGVec3<T>& normal, T dist) :
|
SGPlane(const SGVec3<T>& normal, const T& dist) :
|
||||||
_normal(normal), _dist(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]) :
|
SGPlane(const SGVec3<T> vertices[3]) :
|
||||||
_normal(normalize(cross(vertices[1] - vertices[0],
|
_normal(normalize(cross(vertices[1] - vertices[0],
|
||||||
vertices[2] - vertices[0]))),
|
vertices[2] - vertices[0]))),
|
||||||
_dist(-dot(_normal, 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)
|
void setNormal(const SGVec3<T>& normal)
|
||||||
{ _normal = normal; }
|
{ _normal = normal; }
|
||||||
@@ -42,6 +53,10 @@ public:
|
|||||||
const T& getDist() const
|
const T& getDist() const
|
||||||
{ return _dist; }
|
{ 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
|
/// That is the distance where we measure positive in direction of the normal
|
||||||
T getPositiveDist() const
|
T getPositiveDist() const
|
||||||
{ return -_dist; }
|
{ 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
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -26,42 +26,13 @@
|
|||||||
#undef max
|
#undef max
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||||
#include <osg/Quat>
|
#include <osg/Quat>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Quaternion Class
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct SGQuatStorage {
|
class SGQuat {
|
||||||
/// 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> {
|
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
|
||||||
@@ -84,8 +55,6 @@ public:
|
|||||||
/// make sure it has at least 4 elements
|
/// make sure it has at least 4 elements
|
||||||
explicit SGQuat(const T* d)
|
explicit SGQuat(const T* d)
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
{ 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
|
/// Return a unit quaternion
|
||||||
static SGQuat unit(void)
|
static SGQuat unit(void)
|
||||||
@@ -158,48 +127,11 @@ public:
|
|||||||
static SGQuat fromLonLat(const SGGeod& geod)
|
static SGQuat fromLonLat(const SGGeod& geod)
|
||||||
{ return fromLonLatRad(geod.getLongitudeRad(), geod.getLatitudeRad()); }
|
{ 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
|
/// Create a quaternion from the angle axis representation
|
||||||
static SGQuat fromAngleAxis(T angle, const SGVec3<T>& axis)
|
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);
|
return fromRealImag(cos(angle2), T(sin(angle2))*axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,34 +145,36 @@ public:
|
|||||||
{
|
{
|
||||||
T nAxis = norm(axis);
|
T nAxis = norm(axis);
|
||||||
if (nAxis <= SGLimits<T>::min())
|
if (nAxis <= SGLimits<T>::min())
|
||||||
return SGQuat(1, 0, 0, 0);
|
return SGQuat::unit();
|
||||||
T angle2 = 0.5*nAxis;
|
T angle2 = T(0.5)*nAxis;
|
||||||
return fromRealImag(cos(angle2), T(sin(angle2)/nAxis)*axis);
|
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)
|
static SGQuat fromRotateTo(const SGVec3<T>& from, const SGVec3<T>& to)
|
||||||
{
|
{
|
||||||
T nfrom = norm(from);
|
T nfrom = norm(from);
|
||||||
T nto = norm(to);
|
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::unit();
|
||||||
|
|
||||||
return SGQuat::fromRotateToNorm((1/nfrom)*from, (1/nto)*to);
|
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,
|
static SGQuat fromRotateTo(const SGVec3<T>& v1, unsigned i1,
|
||||||
const SGVec3<T>& v2, unsigned i2)
|
const SGVec3<T>& v2, unsigned i2)
|
||||||
{
|
{
|
||||||
T nrmv1 = norm(v1);
|
T nrmv1 = norm(v1);
|
||||||
T nrmv2 = norm(v2);
|
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();
|
return SGQuat::unit();
|
||||||
|
|
||||||
SGVec3<T> nv1 = (1/nrmv1)*v1;
|
SGVec3<T> nv1 = (1/nrmv1)*v1;
|
||||||
SGVec3<T> nv2 = (1/nrmv2)*v2;
|
SGVec3<T> nv2 = (1/nrmv2)*v2;
|
||||||
T dv1v2 = dot(nv1, nv2);
|
T dv1v2 = dot(nv1, nv2);
|
||||||
if (fabs(fabs(dv1v2)-1) < SGLimits<T>::epsilon())
|
if (fabs(fabs(dv1v2)-1) <= SGLimits<T>::epsilon())
|
||||||
return SGQuat::unit();
|
return SGQuat::unit();
|
||||||
|
|
||||||
// The target vector for the first rotation
|
// The target vector for the first rotation
|
||||||
@@ -261,12 +195,12 @@ public:
|
|||||||
|
|
||||||
SGVec3<T> tnv2 = q.transform(nv2);
|
SGVec3<T> tnv2 = q.transform(nv2);
|
||||||
T cosang = dot(nto2, tnv2);
|
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)
|
if (cos05ang <= 0)
|
||||||
cosang = T(0);
|
cosang = 0;
|
||||||
cos05ang = sqrt(cos05ang);
|
cos05ang = sqrt(cos05ang);
|
||||||
T sig = dot(nto1, cross(nto2, tnv2));
|
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)
|
if (sin05ang <= 0)
|
||||||
sin05ang = 0;
|
sin05ang = 0;
|
||||||
sin05ang = copysign(sqrt(sin05ang), sig);
|
sin05ang = copysign(sqrt(sin05ang), sig);
|
||||||
@@ -329,24 +263,24 @@ public:
|
|||||||
|
|
||||||
T num = 2*(y()*z() + w()*x());
|
T num = 2*(y()*z() + w()*x());
|
||||||
T den = sqrQW - sqrQX - sqrQY + sqrQZ;
|
T den = sqrQW - sqrQX - sqrQY + sqrQZ;
|
||||||
if (fabs(den) < SGLimits<T>::min() &&
|
if (fabs(den) <= SGLimits<T>::min() &&
|
||||||
fabs(num) < SGLimits<T>::min())
|
fabs(num) <= SGLimits<T>::min())
|
||||||
xRad = 0;
|
xRad = 0;
|
||||||
else
|
else
|
||||||
xRad = atan2(num, den);
|
xRad = atan2(num, den);
|
||||||
|
|
||||||
T tmp = 2*(x()*z() - w()*y());
|
T tmp = 2*(x()*z() - w()*y());
|
||||||
if (tmp < -1)
|
if (tmp <= -1)
|
||||||
yRad = 0.5*SGMisc<T>::pi();
|
yRad = T(0.5)*SGMisc<T>::pi();
|
||||||
else if (1 < tmp)
|
else if (1 <= tmp)
|
||||||
yRad = -0.5*SGMisc<T>::pi();
|
yRad = -T(0.5)*SGMisc<T>::pi();
|
||||||
else
|
else
|
||||||
yRad = -asin(tmp);
|
yRad = -asin(tmp);
|
||||||
|
|
||||||
num = 2*(x()*y() + w()*z());
|
num = 2*(x()*y() + w()*z());
|
||||||
den = sqrQW + sqrQX - sqrQY - sqrQZ;
|
den = sqrQW + sqrQX - sqrQY - sqrQZ;
|
||||||
if (fabs(den) < SGLimits<T>::min() &&
|
if (fabs(den) <= SGLimits<T>::min() &&
|
||||||
fabs(num) < SGLimits<T>::min())
|
fabs(num) <= SGLimits<T>::min())
|
||||||
zRad = 0;
|
zRad = 0;
|
||||||
else {
|
else {
|
||||||
T psi = atan2(num, den);
|
T psi = atan2(num, den);
|
||||||
@@ -369,14 +303,14 @@ public:
|
|||||||
void getAngleAxis(T& angle, SGVec3<T>& axis) const
|
void getAngleAxis(T& angle, SGVec3<T>& axis) const
|
||||||
{
|
{
|
||||||
T nrm = norm(*this);
|
T nrm = norm(*this);
|
||||||
if (nrm < SGLimits<T>::min()) {
|
if (nrm <= SGLimits<T>::min()) {
|
||||||
angle = 0;
|
angle = 0;
|
||||||
axis = SGVec3<T>(0, 0, 0);
|
axis = SGVec3<T>(0, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
T rNrm = 1/nrm;
|
T rNrm = 1/nrm;
|
||||||
angle = acos(SGMisc<T>::max(-1, SGMisc<T>::min(1, rNrm*w())));
|
angle = acos(SGMisc<T>::max(-1, SGMisc<T>::min(1, rNrm*w())));
|
||||||
T sAng = sin(angle);
|
T sAng = sin(angle);
|
||||||
if (fabs(sAng) < SGLimits<T>::min())
|
if (fabs(sAng) <= SGLimits<T>::min())
|
||||||
axis = SGVec3<T>(1, 0, 0);
|
axis = SGVec3<T>(1, 0, 0);
|
||||||
else
|
else
|
||||||
axis = (rNrm/sAng)*imag(*this);
|
axis = (rNrm/sAng)*imag(*this);
|
||||||
@@ -432,17 +366,11 @@ public:
|
|||||||
{ return data()[3]; }
|
{ return data()[3]; }
|
||||||
|
|
||||||
/// Get the data pointer
|
/// Get the data pointer
|
||||||
using SGQuatStorage<T>::data;
|
const T (&data(void) const)[4]
|
||||||
|
{ return _data; }
|
||||||
/// Readonly interface function to ssg's sgQuat/sgdQuat
|
/// Get the data pointer
|
||||||
const T (&sg(void) const)[4]
|
T (&data(void))[4]
|
||||||
{ return data(); }
|
{ 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;
|
|
||||||
|
|
||||||
/// Inplace addition
|
/// Inplace addition
|
||||||
SGQuat& operator+=(const SGQuat& v)
|
SGQuat& operator+=(const SGQuat& v)
|
||||||
@@ -493,10 +421,10 @@ public:
|
|||||||
{
|
{
|
||||||
SGQuat deriv;
|
SGQuat deriv;
|
||||||
|
|
||||||
deriv.w() = 0.5*(-x()*angVel(0) - y()*angVel(1) - z()*angVel(2));
|
deriv.w() = T(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.x() = T(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.y() = T(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.z() = T(0.5)*(-y()*angVel(0) + x()*angVel(1) + w()*angVel(2));
|
||||||
|
|
||||||
return deriv;
|
return deriv;
|
||||||
}
|
}
|
||||||
@@ -521,7 +449,7 @@ private:
|
|||||||
// in the interval [-pi,pi]. That means that 0.5*angle is in the interval
|
// 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.
|
// [-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:
|
// 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.
|
// Now our assumption of angles <= 90 deg comes in play.
|
||||||
@@ -561,6 +489,8 @@ private:
|
|||||||
SGQuat q2 = SGQuat::fromRotateToSmaller90Deg(-cosang, -from, to);
|
SGQuat q2 = SGQuat::fromRotateToSmaller90Deg(-cosang, -from, to);
|
||||||
return q1*q2;
|
return q1*q2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T _data[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Unary +, do nothing ...
|
/// 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
|
// need the scales now, if the angle is very small, do linear interpolation
|
||||||
// to avoid instabilities
|
// to avoid instabilities
|
||||||
T scale0, scale1;
|
T scale0, scale1;
|
||||||
if (fabs(o) < SGLimits<T>::epsilon()) {
|
if (fabs(o) <= SGLimits<T>::epsilon()) {
|
||||||
scale0 = 1 - t;
|
scale0 = 1 - t;
|
||||||
scale1 = t;
|
scale1 = t;
|
||||||
} else {
|
} else {
|
||||||
@@ -790,4 +720,16 @@ SGQuatd
|
|||||||
toQuatd(const SGQuatf& v)
|
toQuatd(const SGQuatf& v)
|
||||||
{ return SGQuatd(v(0), v(1), v(2), v(3)); }
|
{ 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
|
#endif
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ public:
|
|||||||
SGRay(const SGVec3<T>& origin, const SGVec3<T>& dir) :
|
SGRay(const SGVec3<T>& origin, const SGVec3<T>& dir) :
|
||||||
_origin(origin), _direction(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)
|
void set(const SGVec3<T>& origin, const SGVec3<T>& dir)
|
||||||
{ _origin = origin; _direction = dir; }
|
{ _origin = origin; _direction = dir; }
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ public:
|
|||||||
_center(center),
|
_center(center),
|
||||||
_radius(radius)
|
_radius(radius)
|
||||||
{ }
|
{ }
|
||||||
|
template<typename S>
|
||||||
|
explicit SGSphere(const SGSphere<S>& sphere) :
|
||||||
|
_center(sphere.getCenter()),
|
||||||
|
_radius(sphere.getRadius())
|
||||||
|
{ }
|
||||||
|
|
||||||
const SGVec3<T>& getCenter() const
|
const SGVec3<T>& getCenter() const
|
||||||
{ return _center; }
|
{ return _center; }
|
||||||
@@ -41,7 +46,7 @@ public:
|
|||||||
T getRadius2() const
|
T getRadius2() const
|
||||||
{ return _radius*_radius; }
|
{ return _radius*_radius; }
|
||||||
|
|
||||||
const bool empty() const
|
bool empty() const
|
||||||
{ return !valid(); }
|
{ return !valid(); }
|
||||||
|
|
||||||
bool valid() const
|
bool valid() const
|
||||||
@@ -68,6 +73,65 @@ public:
|
|||||||
_radius = newRadius;
|
_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:
|
private:
|
||||||
SGVec3<T> _center;
|
SGVec3<T> _center;
|
||||||
T _radius;
|
T _radius;
|
||||||
|
|||||||
@@ -41,14 +41,8 @@ public:
|
|||||||
_d[1] = v[2] - v[0];
|
_d[1] = v[2] - v[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
SGVec3d getCenter() const
|
SGVec3<T> getCenter() const
|
||||||
{
|
{ return _v0 + T(1)/T(3)*(_d[0] + _d[1]); }
|
||||||
SGBoxd box;
|
|
||||||
box.expandBy(_v0);
|
|
||||||
box.expandBy(_v0 + _d[0]);
|
|
||||||
box.expandBy(_v0 + _d[1]);
|
|
||||||
return box.getCenter();
|
|
||||||
}
|
|
||||||
|
|
||||||
// note that the index is unchecked
|
// note that the index is unchecked
|
||||||
SGVec3<T> getVertex(unsigned i) const
|
SGVec3<T> getVertex(unsigned i) const
|
||||||
@@ -77,6 +71,16 @@ public:
|
|||||||
_d[0] = _d[1];
|
_d[0] = _d[1];
|
||||||
_d[1] = tmp;
|
_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:
|
private:
|
||||||
/// Store one vertex directly, _d is the offset of the other two
|
/// Store one vertex directly, _d is the offset of the other two
|
||||||
/// vertices wrt the base vertex
|
/// vertices wrt the base vertex
|
||||||
|
|||||||
+56
-64
@@ -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
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -22,58 +22,14 @@
|
|||||||
#include <ieeefp.h>
|
#include <ieeefp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||||
#include <osg/Vec2f>
|
#include <osg/Vec2f>
|
||||||
#include <osg/Vec2d>
|
#include <osg/Vec2d>
|
||||||
|
#endif
|
||||||
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; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// 2D Vector Class
|
/// 2D Vector Class
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class SGVec2 : protected SGVec2Storage<T> {
|
class SGVec2 {
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
|
||||||
@@ -96,9 +52,8 @@ public:
|
|||||||
/// make sure it has at least 2 elements
|
/// make sure it has at least 2 elements
|
||||||
explicit SGVec2(const T* d)
|
explicit SGVec2(const T* d)
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; }
|
{ data()[0] = d[0]; data()[1] = d[1]; }
|
||||||
explicit SGVec2(const osg::Vec2f& d)
|
template<typename S>
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; }
|
explicit SGVec2(const SGVec2<S>& d)
|
||||||
explicit SGVec2(const osg::Vec2d& d)
|
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; }
|
{ data()[0] = d[0]; data()[1] = d[1]; }
|
||||||
|
|
||||||
/// Access by index, the index is unchecked
|
/// Access by index, the index is unchecked
|
||||||
@@ -128,18 +83,12 @@ public:
|
|||||||
T& y(void)
|
T& y(void)
|
||||||
{ return data()[1]; }
|
{ return data()[1]; }
|
||||||
|
|
||||||
/// Get the data pointer
|
/// Access raw data
|
||||||
using SGVec2Storage<T>::data;
|
const T (&data(void) const)[2]
|
||||||
|
{ return _data; }
|
||||||
/// Readonly interface function to ssg's sgVec2/sgdVec2
|
/// Access raw data
|
||||||
const T (&sg(void) const)[2]
|
T (&data(void))[2]
|
||||||
{ return data(); }
|
{ 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;
|
|
||||||
|
|
||||||
/// Inplace addition
|
/// Inplace addition
|
||||||
SGVec2& operator+=(const SGVec2& v)
|
SGVec2& operator+=(const SGVec2& v)
|
||||||
@@ -164,6 +113,9 @@ public:
|
|||||||
{ return SGVec2(1, 0); }
|
{ return SGVec2(1, 0); }
|
||||||
static SGVec2 e2(void)
|
static SGVec2 e2(void)
|
||||||
{ return SGVec2(0, 1); }
|
{ return SGVec2(0, 1); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T _data[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Unary +, do nothing ...
|
/// Unary +, do nothing ...
|
||||||
@@ -292,7 +244,12 @@ template<typename T>
|
|||||||
inline
|
inline
|
||||||
SGVec2<T>
|
SGVec2<T>
|
||||||
normalize(const SGVec2<T>& v)
|
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
|
/// Return true if exactly the same
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -379,6 +336,18 @@ T
|
|||||||
distSqr(const SGVec2<T>& v1, const SGVec2<T>& v2)
|
distSqr(const SGVec2<T>& v1, const SGVec2<T>& v2)
|
||||||
{ SGVec2<T> tmp = v1 - v2; return dot(tmp, tmp); }
|
{ 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
|
#ifndef NDEBUG
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline
|
inline
|
||||||
@@ -406,4 +375,27 @@ SGVec2d
|
|||||||
toVec2d(const SGVec2f& v)
|
toVec2d(const SGVec2f& v)
|
||||||
{ return SGVec2d(v(0), v(1)); }
|
{ 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
|
#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
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -18,58 +18,14 @@
|
|||||||
#ifndef SGVec3_H
|
#ifndef SGVec3_H
|
||||||
#define SGVec3_H
|
#define SGVec3_H
|
||||||
|
|
||||||
|
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
#include <osg/Vec3d>
|
#include <osg/Vec3d>
|
||||||
|
#endif
|
||||||
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; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// 3D Vector Class
|
/// 3D Vector Class
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class SGVec3 : protected SGVec3Storage<T> {
|
class SGVec3 {
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
|
||||||
@@ -92,9 +48,8 @@ public:
|
|||||||
/// make sure it has at least 3 elements
|
/// make sure it has at least 3 elements
|
||||||
explicit SGVec3(const T* d)
|
explicit SGVec3(const T* d)
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
||||||
explicit SGVec3(const osg::Vec3f& d)
|
template<typename S>
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
explicit SGVec3(const SGVec3<S>& d)
|
||||||
explicit SGVec3(const osg::Vec3d& d)
|
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
||||||
explicit SGVec3(const SGVec2<T>& v2, const T& v3 = 0)
|
explicit SGVec3(const SGVec2<T>& v2, const T& v3 = 0)
|
||||||
{ data()[0] = v2[0]; data()[1] = v2[1]; data()[2] = v3; }
|
{ data()[0] = v2[0]; data()[1] = v2[1]; data()[2] = v3; }
|
||||||
@@ -132,18 +87,12 @@ public:
|
|||||||
T& z(void)
|
T& z(void)
|
||||||
{ return data()[2]; }
|
{ return data()[2]; }
|
||||||
|
|
||||||
/// Get the data pointer
|
/// Readonly raw storage interface
|
||||||
using SGVec3Storage<T>::data;
|
const T (&data(void) const)[3]
|
||||||
|
{ return _data; }
|
||||||
/// Readonly interface function to ssg's sgVec3/sgdVec3
|
/// Readonly raw storage interface
|
||||||
const T (&sg(void) const)[3]
|
T (&data(void))[3]
|
||||||
{ return data(); }
|
{ 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;
|
|
||||||
|
|
||||||
/// Inplace addition
|
/// Inplace addition
|
||||||
SGVec3& operator+=(const SGVec3& v)
|
SGVec3& operator+=(const SGVec3& v)
|
||||||
@@ -177,6 +126,9 @@ public:
|
|||||||
/// Constructor. Initialize by a geocentric coordinate
|
/// Constructor. Initialize by a geocentric coordinate
|
||||||
/// Note that this conversion is relatively expensive to compute
|
/// Note that this conversion is relatively expensive to compute
|
||||||
static SGVec3 fromGeoc(const SGGeoc& geoc);
|
static SGVec3 fromGeoc(const SGGeoc& geoc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
T _data[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
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>
|
template<typename T>
|
||||||
inline
|
inline
|
||||||
SGVec3<T>
|
SGVec3<T>
|
||||||
normalize(const SGVec3<T>& v)
|
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
|
/// Return true if exactly the same
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -496,6 +454,18 @@ T
|
|||||||
distSqr(const SGVec3<T>& v1, const SGVec3<T>& v2)
|
distSqr(const SGVec3<T>& v1, const SGVec3<T>& v2)
|
||||||
{ SGVec3<T> tmp = v1 - v2; return dot(tmp, tmp); }
|
{ 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
|
#ifndef NDEBUG
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline
|
inline
|
||||||
@@ -524,4 +494,26 @@ SGVec3d
|
|||||||
toVec3d(const SGVec3f& v)
|
toVec3d(const SGVec3f& v)
|
||||||
{ return SGVec3d(v(0), v(1), v(2)); }
|
{ 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
|
#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
|
// This library is free software; you can redistribute it and/or
|
||||||
// modify it under the terms of the GNU Library General Public
|
// modify it under the terms of the GNU Library General Public
|
||||||
@@ -18,58 +18,14 @@
|
|||||||
#ifndef SGVec4_H
|
#ifndef SGVec4_H
|
||||||
#define SGVec4_H
|
#define SGVec4_H
|
||||||
|
|
||||||
|
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||||
#include <osg/Vec4f>
|
#include <osg/Vec4f>
|
||||||
#include <osg/Vec4d>
|
#include <osg/Vec4d>
|
||||||
|
#endif
|
||||||
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; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// 4D Vector Class
|
/// 4D Vector Class
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class SGVec4 : protected SGVec4Storage<T> {
|
class SGVec4 {
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
|
||||||
@@ -92,14 +48,12 @@ public:
|
|||||||
/// make sure it has at least 3 elements
|
/// make sure it has at least 3 elements
|
||||||
explicit SGVec4(const T* d)
|
explicit SGVec4(const T* d)
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||||
explicit SGVec4(const osg::Vec4f& d)
|
template<typename S>
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
explicit SGVec4(const SGVec4<S>& d)
|
||||||
explicit SGVec4(const osg::Vec4d& d)
|
|
||||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
{ 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)
|
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; }
|
{ data()[0] = v3[0]; data()[1] = v3[1]; data()[2] = v3[2]; data()[3] = v4; }
|
||||||
|
|
||||||
|
|
||||||
/// Access by index, the index is unchecked
|
/// Access by index, the index is unchecked
|
||||||
const T& operator()(unsigned i) const
|
const T& operator()(unsigned i) const
|
||||||
{ return data()[i]; }
|
{ return data()[i]; }
|
||||||
@@ -139,18 +93,12 @@ public:
|
|||||||
T& w(void)
|
T& w(void)
|
||||||
{ return data()[3]; }
|
{ return data()[3]; }
|
||||||
|
|
||||||
/// Get the data pointer
|
/// Readonly raw storage interface
|
||||||
using SGVec4Storage<T>::data;
|
const T (&data(void) const)[4]
|
||||||
|
{ return _data; }
|
||||||
/// Readonly interface function to ssg's sgVec4/sgdVec4
|
/// Readonly raw storage interface
|
||||||
const T (&sg(void) const)[4]
|
T (&data(void))[4]
|
||||||
{ return data(); }
|
{ 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;
|
|
||||||
|
|
||||||
/// Inplace addition
|
/// Inplace addition
|
||||||
SGVec4& operator+=(const SGVec4& v)
|
SGVec4& operator+=(const SGVec4& v)
|
||||||
@@ -179,6 +127,9 @@ public:
|
|||||||
{ return SGVec4(0, 0, 1, 0); }
|
{ return SGVec4(0, 0, 1, 0); }
|
||||||
static SGVec4 e4(void)
|
static SGVec4 e4(void)
|
||||||
{ return SGVec4(0, 0, 0, 1); }
|
{ return SGVec4(0, 0, 0, 1); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T _data[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Unary +, do nothing ...
|
/// Unary +, do nothing ...
|
||||||
@@ -337,7 +288,12 @@ template<typename T>
|
|||||||
inline
|
inline
|
||||||
SGVec4<T>
|
SGVec4<T>
|
||||||
normalize(const SGVec4<T>& v)
|
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
|
/// Return true if exactly the same
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -432,6 +388,18 @@ T
|
|||||||
distSqr(const SGVec4<T>& v1, const SGVec4<T>& v2)
|
distSqr(const SGVec4<T>& v1, const SGVec4<T>& v2)
|
||||||
{ SGVec4<T> tmp = v1 - v2; return dot(tmp, tmp); }
|
{ 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
|
#ifndef NDEBUG
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline
|
inline
|
||||||
@@ -460,4 +428,26 @@ SGVec4d
|
|||||||
toVec4d(const SGVec4f& v)
|
toVec4d(const SGVec4f& v)
|
||||||
{ return SGVec4d(v(0), v(1), v(2), v(3)); }
|
{ 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
|
#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$
|
// $Id$
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <simgear_config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
@@ -33,6 +36,8 @@
|
|||||||
|
|
||||||
#include "interpolater.hxx"
|
#include "interpolater.hxx"
|
||||||
|
|
||||||
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
// Constructor -- starts with an empty table.
|
// Constructor -- starts with an empty table.
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
#include "simgear/structure/SGReferenced.hxx"
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <simgear/math/point3d.hxx>
|
class Point3D;
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|||||||
+18
-16
@@ -29,6 +29,20 @@
|
|||||||
#include "vector.hxx"
|
#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,
|
// Given a point p, and a line through p0 with direction vector d,
|
||||||
// find the closest point (p1) on the line
|
// find the closest point (p1) on the line
|
||||||
void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0,
|
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);
|
sgSubVec3(u, p, p0);
|
||||||
|
|
||||||
// calculate the projection, u1, of u along d.
|
// calculate the projection, u1, of u along d.
|
||||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
sgProjection(u1, u, d);
|
||||||
sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) );
|
|
||||||
|
|
||||||
// calculate the point p1 along the line that is closest to p
|
// calculate the point p1 along the line that is closest to p
|
||||||
// p0 = p1 + u1
|
// p0 = p1 + u1
|
||||||
@@ -60,12 +73,7 @@ void sgdClosestPointToLine( sgdVec3 p1, const sgdVec3 p, const sgdVec3 p0,
|
|||||||
sgdSubVec3(u, p, p0);
|
sgdSubVec3(u, p, p0);
|
||||||
|
|
||||||
// calculate the projection, u1, of u along d.
|
// calculate the projection, u1, of u along d.
|
||||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
sgProjection(u1, u, d);
|
||||||
double ud = sgdScalarProductVec3(u, d);
|
|
||||||
double dd = sgdScalarProductVec3(d, d);
|
|
||||||
double tmp = ud / dd;
|
|
||||||
|
|
||||||
sgdScaleVec3(u1, d, tmp);;
|
|
||||||
|
|
||||||
// calculate the point p1 along the line that is closest to p
|
// calculate the point p1 along the line that is closest to p
|
||||||
// p0 = p1 + u1
|
// p0 = p1 + u1
|
||||||
@@ -84,8 +92,7 @@ double sgClosestPointToLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
|||||||
sgSubVec3(u, p, p0);
|
sgSubVec3(u, p, p0);
|
||||||
|
|
||||||
// calculate the projection, u1, of u along d.
|
// calculate the projection, u1, of u along d.
|
||||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
sgProjection(u1, u, d);
|
||||||
sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) );
|
|
||||||
|
|
||||||
// v = u - u1 = vector from closest point on line, p1, to the
|
// v = u - u1 = vector from closest point on line, p1, to the
|
||||||
// original point, p.
|
// original point, p.
|
||||||
@@ -106,12 +113,7 @@ double sgdClosestPointToLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
|||||||
sgdSubVec3(u, p, p0);
|
sgdSubVec3(u, p, p0);
|
||||||
|
|
||||||
// calculate the projection, u1, of u along d.
|
// calculate the projection, u1, of u along d.
|
||||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
sgProjection(u1, u, d);
|
||||||
double ud = sgdScalarProductVec3(u, d);
|
|
||||||
double dd = sgdScalarProductVec3(d, d);
|
|
||||||
double tmp = ud / dd;
|
|
||||||
|
|
||||||
sgdScaleVec3(u1, d, tmp);;
|
|
||||||
|
|
||||||
// v = u - u1 = vector from closest point on line, p1, to the
|
// v = u - u1 = vector from closest point on line, p1, to the
|
||||||
// original point, p.
|
// 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 normal (in) normal vector for the plane
|
||||||
* @param v0 (in) a point on the plane
|
* @param v0 (in) a point on the plane
|
||||||
* @param vec (in) the vector to map onto the plane
|
* @param vec (in) the vector to map onto the plane
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ libsgmisc_a_SOURCES = \
|
|||||||
interpolator.cxx \
|
interpolator.cxx \
|
||||||
PathOptions.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_SOURCES = tabbed_values_test.cxx
|
||||||
tabbed_value_test_LDADD = \
|
#tabbed_value_test_LDADD = \
|
||||||
libsgmisc.a \
|
# libsgmisc.a \
|
||||||
$(top_builddir)/simgear/xml/libsgxml.a \
|
# $(top_builddir)/simgear/xml/libsgxml.a \
|
||||||
$(top_builddir)/simgear/debug/libsgdebug.a
|
# $(top_builddir)/simgear/debug/libsgdebug.a
|
||||||
|
|
||||||
$(top_builddir)/simgear/xml/libsgxml.a:
|
$(top_builddir)/simgear/xml/libsgxml.a:
|
||||||
cd $(top_builddir)/simgear/xml && $(MAKE) $(AM_MAKEFLAGS) 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:
|
$(top_builddir)/simgear/debug/libsgdebug.a:
|
||||||
cd $(top_builddir)/simgear/debug && $(MAKE) $(AM_MAKEFLAGS) 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)
|
INCLUDES = -I$(top_srcdir)
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include "interpolator.hxx"
|
#include "interpolator.hxx"
|
||||||
|
|
||||||
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
|
||||||
void SGInterpolator::addNew(SGPropertyNode* prop, int nPoints)
|
void SGInterpolator::addNew(SGPropertyNode* prop, int nPoints)
|
||||||
{
|
{
|
||||||
// Set the property type to a double, if it isn't already, and
|
// Set the property type to a double, if it isn't already, and
|
||||||
|
|||||||
@@ -25,6 +25,9 @@
|
|||||||
|
|
||||||
#include "strutils.hxx"
|
#include "strutils.hxx"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
namespace strutils {
|
namespace strutils {
|
||||||
|
|
||||||
|
|||||||
@@ -30,16 +30,12 @@
|
|||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
namespace simgear {
|
namespace simgear {
|
||||||
namespace strutils {
|
namespace strutils {
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * atof() wrapper for "string" type
|
// * atof() wrapper for "string" type
|
||||||
@@ -64,9 +60,9 @@ namespace simgear {
|
|||||||
* @param s String to strip.
|
* @param s String to strip.
|
||||||
* @return The stripped string.
|
* @return The stripped string.
|
||||||
*/
|
*/
|
||||||
string lstrip( const string& s );
|
std::string lstrip( const std::string& s );
|
||||||
string rstrip( const string& s );
|
std::string rstrip( const std::string& s );
|
||||||
string strip( const string& s );
|
std::string strip( const std::string& s );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split a string into a words using 'sep' as the delimiter string.
|
* 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.
|
* resulting in at most maxsplit+1 words.
|
||||||
* @return Array of words.
|
* @return Array of words.
|
||||||
*/
|
*/
|
||||||
vector<string>
|
std::vector<std::string>
|
||||||
split( const string& s,
|
split( const std::string& s,
|
||||||
const char* sep = 0,
|
const char* sep = 0,
|
||||||
int maxsplit = 0 );
|
int maxsplit = 0 );
|
||||||
|
|
||||||
} // end namespace strutils
|
} // end namespace strutils
|
||||||
} // end namespace simgear
|
} // end namespace simgear
|
||||||
|
|
||||||
#endif // STRUTILS_H
|
#endif // STRUTILS_H
|
||||||
|
|||||||
@@ -21,10 +21,10 @@
|
|||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "tabbed_values.hxx"
|
#include "tabbed_values.hxx"
|
||||||
|
|
||||||
#include "assert.h"
|
|
||||||
|
|
||||||
SGTabbedValues::SGTabbedValues(const char *line) :
|
SGTabbedValues::SGTabbedValues(const char *line) :
|
||||||
_line(line)
|
_line(line)
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ enter this in the official comments in case I forget again. :-)
|
|||||||
|
|
||||||
#include "texcoord.hxx"
|
#include "texcoord.hxx"
|
||||||
|
|
||||||
|
#include <simgear/math/point3d.hxx>
|
||||||
// using std::cout;
|
// using std::cout;
|
||||||
// using std::endl;
|
// using std::endl;
|
||||||
|
|
||||||
|
|||||||
+38
-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));
|
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)
|
static void ghostDestroy(void* g)
|
||||||
{
|
{
|
||||||
struct naIOGhost* io = (struct naIOGhost*)g;
|
struct naIOGhost* io = (struct naIOGhost*)g;
|
||||||
@@ -111,6 +120,11 @@ static int iotell(naContext c, void* f)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ioflush(naContext c, void* f)
|
||||||
|
{
|
||||||
|
if(fflush(f)) naRuntimeError(c, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
static void iodestroy(void* f)
|
static void iodestroy(void* f)
|
||||||
{
|
{
|
||||||
if(f != stdin && f != stdout && f != stderr)
|
if(f != stdin && f != stdout && f != stderr)
|
||||||
@@ -118,7 +132,7 @@ static void iodestroy(void* f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct naIOType naStdIOType = { ioclose, ioread, iowrite, ioseek,
|
struct naIOType naStdIOType = { ioclose, ioread, iowrite, ioseek,
|
||||||
iotell, iodestroy };
|
iotell, ioflush, iodestroy };
|
||||||
|
|
||||||
naRef naIOGhost(naContext c, FILE* f)
|
naRef naIOGhost(naContext c, FILE* f)
|
||||||
{
|
{
|
||||||
@@ -181,6 +195,26 @@ static naRef f_readln(naContext ctx, naRef me, int argc, naRef* args)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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
|
||||||
|
#define S_ISLNK(m) 0
|
||||||
|
#define S_ISSOCK(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)
|
static naRef f_stat(naContext ctx, naRef me, int argc, naRef* args)
|
||||||
{
|
{
|
||||||
int n=0;
|
int n=0;
|
||||||
@@ -192,11 +226,12 @@ static naRef f_stat(naContext ctx, naRef me, int argc, naRef* args)
|
|||||||
naRuntimeError(ctx, strerror(errno));
|
naRuntimeError(ctx, strerror(errno));
|
||||||
}
|
}
|
||||||
result = naNewVector(ctx);
|
result = naNewVector(ctx);
|
||||||
naVec_setsize(result, 11);
|
naVec_setsize(result, 12);
|
||||||
#define FLD(x) naVec_set(result, n++, naNum(s.st_##x));
|
#define FLD(x) naVec_set(result, n++, naNum(s.st_##x));
|
||||||
FLD(dev); FLD(ino); FLD(mode); FLD(nlink); FLD(uid); FLD(gid);
|
FLD(dev); FLD(ino); FLD(mode); FLD(nlink); FLD(uid); FLD(gid);
|
||||||
FLD(rdev); FLD(size); FLD(atime); FLD(mtime); FLD(ctime);
|
FLD(rdev); FLD(size); FLD(atime); FLD(mtime); FLD(ctime);
|
||||||
#undef FLD
|
#undef FLD
|
||||||
|
naVec_set(result, n++, ftype(ctx, s.st_mode));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +241,7 @@ static naCFuncItem funcs[] = {
|
|||||||
{ "write", f_write },
|
{ "write", f_write },
|
||||||
{ "seek", f_seek },
|
{ "seek", f_seek },
|
||||||
{ "tell", f_tell },
|
{ "tell", f_tell },
|
||||||
|
{ "flush", f_flush },
|
||||||
{ "open", f_open },
|
{ "open", f_open },
|
||||||
{ "readln", f_readln },
|
{ "readln", f_readln },
|
||||||
{ "stat", f_stat },
|
{ "stat", f_stat },
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ struct naIOType {
|
|||||||
int (*write)(naContext c, void* f, char* buf, unsigned int len);
|
int (*write)(naContext c, void* f, char* buf, unsigned int len);
|
||||||
void (*seek) (naContext c, void* f, unsigned int off, int whence);
|
void (*seek) (naContext c, void* f, unsigned int off, int whence);
|
||||||
int (*tell) (naContext c, void* f);
|
int (*tell) (naContext c, void* f);
|
||||||
|
void (*flush) (naContext c, void* f);
|
||||||
void (*destroy)(void* f);
|
void (*destroy)(void* f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
* tested */
|
* tested */
|
||||||
# define NASAL_NAN64
|
# define NASAL_NAN64
|
||||||
#elif defined(_M_IX86) || defined(i386) || defined(__x86_64) || \
|
#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
|
# define NASAL_LE
|
||||||
#elif defined(__sparc) || defined(__ppc__) || defined(__PPC) || \
|
#elif defined(__sparc) || defined(__ppc__) || defined(__PPC) || \
|
||||||
defined(__mips) || defined(__ARMEB__)
|
defined(__mips) || defined(__ARMEB__)
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#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,12 +5,15 @@ lib_LIBRARIES = libsgprops.a
|
|||||||
include_HEADERS = \
|
include_HEADERS = \
|
||||||
condition.hxx \
|
condition.hxx \
|
||||||
props.hxx \
|
props.hxx \
|
||||||
props_io.hxx
|
props_io.hxx \
|
||||||
|
AtomicChangeListener.hxx \
|
||||||
|
ExtendedPropertyAdapter.hxx
|
||||||
|
|
||||||
libsgprops_a_SOURCES = \
|
libsgprops_a_SOURCES = \
|
||||||
condition.cxx \
|
condition.cxx \
|
||||||
props.cxx \
|
props.cxx \
|
||||||
props_io.cxx
|
props_io.cxx \
|
||||||
|
AtomicChangeListener.cxx
|
||||||
|
|
||||||
noinst_PROGRAMS = props_test
|
noinst_PROGRAMS = props_test
|
||||||
|
|
||||||
@@ -22,4 +25,10 @@ props_test_LDADD = \
|
|||||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||||
$(top_builddir)/simgear/structure/libsgstructure.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)
|
INCLUDES = -I$(top_srcdir)
|
||||||
|
|||||||
+15
-10
@@ -8,7 +8,7 @@
|
|||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <simgear/compiler.h>
|
# include <simgear_config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// #include <iostream>
|
// #include <iostream>
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
#include "props.hxx"
|
#include "props.hxx"
|
||||||
#include "condition.hxx"
|
#include "condition.hxx"
|
||||||
|
|
||||||
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
|
||||||
using std::istream;
|
using std::istream;
|
||||||
using std::ostream;
|
using std::ostream;
|
||||||
|
|
||||||
@@ -144,8 +146,9 @@ SGOrCondition::addCondition (SGCondition * condition)
|
|||||||
static int
|
static int
|
||||||
doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||||
{
|
{
|
||||||
|
using namespace simgear;
|
||||||
switch (left->getType()) {
|
switch (left->getType()) {
|
||||||
case SGPropertyNode::BOOL: {
|
case props::BOOL: {
|
||||||
bool v1 = left->getBoolValue();
|
bool v1 = left->getBoolValue();
|
||||||
bool v2 = right->getBoolValue();
|
bool v2 = right->getBoolValue();
|
||||||
if (v1 < v2)
|
if (v1 < v2)
|
||||||
@@ -156,7 +159,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
|||||||
return SGComparisonCondition::EQUALS;
|
return SGComparisonCondition::EQUALS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SGPropertyNode::INT: {
|
case props::INT: {
|
||||||
int v1 = left->getIntValue();
|
int v1 = left->getIntValue();
|
||||||
int v2 = right->getIntValue();
|
int v2 = right->getIntValue();
|
||||||
if (v1 < v2)
|
if (v1 < v2)
|
||||||
@@ -167,7 +170,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
|||||||
return SGComparisonCondition::EQUALS;
|
return SGComparisonCondition::EQUALS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SGPropertyNode::LONG: {
|
case props::LONG: {
|
||||||
long v1 = left->getLongValue();
|
long v1 = left->getLongValue();
|
||||||
long v2 = right->getLongValue();
|
long v2 = right->getLongValue();
|
||||||
if (v1 < v2)
|
if (v1 < v2)
|
||||||
@@ -178,7 +181,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
|||||||
return SGComparisonCondition::EQUALS;
|
return SGComparisonCondition::EQUALS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SGPropertyNode::FLOAT: {
|
case props::FLOAT: {
|
||||||
float v1 = left->getFloatValue();
|
float v1 = left->getFloatValue();
|
||||||
float v2 = right->getFloatValue();
|
float v2 = right->getFloatValue();
|
||||||
if (v1 < v2)
|
if (v1 < v2)
|
||||||
@@ -189,7 +192,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
|||||||
return SGComparisonCondition::EQUALS;
|
return SGComparisonCondition::EQUALS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SGPropertyNode::DOUBLE: {
|
case props::DOUBLE: {
|
||||||
double v1 = left->getDoubleValue();
|
double v1 = left->getDoubleValue();
|
||||||
double v2 = right->getDoubleValue();
|
double v2 = right->getDoubleValue();
|
||||||
if (v1 < v2)
|
if (v1 < v2)
|
||||||
@@ -200,9 +203,9 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
|||||||
return SGComparisonCondition::EQUALS;
|
return SGComparisonCondition::EQUALS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SGPropertyNode::STRING:
|
case props::STRING:
|
||||||
case SGPropertyNode::NONE:
|
case props::NONE:
|
||||||
case SGPropertyNode::UNSPECIFIED: {
|
case props::UNSPECIFIED: {
|
||||||
string v1 = left->getStringValue();
|
string v1 = left->getStringValue();
|
||||||
string v2 = right->getStringValue();
|
string v2 = right->getStringValue();
|
||||||
if (v1 < v2)
|
if (v1 < v2)
|
||||||
@@ -213,8 +216,10 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
|||||||
return SGComparisonCondition::EQUALS;
|
return SGComparisonCondition::EQUALS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
throw sg_exception("condition: unrecognized node type in comparison");
|
||||||
}
|
}
|
||||||
throw sg_exception("condition: unrecognized node type in comparison");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+818
-667
File diff suppressed because it is too large
Load Diff
+554
-126
@@ -18,6 +18,10 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
|
||||||
#if PROPS_STANDALONE
|
#if PROPS_STANDALONE
|
||||||
#else
|
#else
|
||||||
@@ -26,10 +30,49 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <simgear/math/SGMathFwd.hxx>
|
||||||
#include <simgear/structure/SGReferenced.hxx>
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
#include <simgear/structure/SGSharedPtr.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
|
#ifdef NONE
|
||||||
#pragma warn A sloppy coder has defined NONE as a macro!
|
#pragma warn A sloppy coder has defined NONE as a macro!
|
||||||
@@ -76,6 +119,68 @@
|
|||||||
#undef STRING
|
#undef STRING
|
||||||
#endif
|
#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.
|
// 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.
|
* Abstract base class for a raw value.
|
||||||
@@ -108,10 +281,7 @@
|
|||||||
* set, and clone the underlying value. The SGRawValue may change
|
* set, and clone the underlying value. The SGRawValue may change
|
||||||
* frequently during a session as a value is retyped or bound and
|
* frequently during a session as a value is retyped or bound and
|
||||||
* unbound to various data source, but the abstract SGPropertyNode
|
* unbound to various data source, but the abstract SGPropertyNode
|
||||||
* layer insulates the application from those changes. The raw value
|
* layer insulates the application from those changes.
|
||||||
* 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>
|
|
||||||
*
|
*
|
||||||
* <p>The SGPropertyNode class always keeps a *copy* of a raw value,
|
* <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
|
* not the original one passed to it; if you override a derived class
|
||||||
@@ -127,9 +297,10 @@
|
|||||||
* @see SGRawValueFunctionsIndexed
|
* @see SGRawValueFunctionsIndexed
|
||||||
* @see SGRawValueMethods
|
* @see SGRawValueMethods
|
||||||
* @see SGRawValueMethodsIndexed
|
* @see SGRawValueMethodsIndexed
|
||||||
|
* @see SGRawValueContainer
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
class SGRawValue
|
class SGRawValue : public SGRawBase<T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -142,7 +313,10 @@ public:
|
|||||||
* may need different kinds of default values (such as epoch for a
|
* may need different kinds of default values (such as epoch for a
|
||||||
* date type). The default value is used when creating new values.
|
* 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.
|
* Return the type tag for this raw value type.
|
||||||
*
|
|
||||||
* The copy will contain its own version of the underlying value
|
|
||||||
* as well.
|
|
||||||
*
|
|
||||||
* @return A deep copy of the current object.
|
|
||||||
*/
|
*/
|
||||||
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.
|
* A raw value bound to a pointer.
|
||||||
*
|
*
|
||||||
@@ -247,8 +434,8 @@ public:
|
|||||||
*
|
*
|
||||||
* The copy will use the same external pointer as the original.
|
* The copy will use the same external pointer as the original.
|
||||||
*/
|
*/
|
||||||
virtual SGRawValue<T> * clone () const {
|
virtual SGRaw* clone () const {
|
||||||
return new SGRawValuePointer<T>(_ptr);
|
return new SGRawValuePointer(_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -304,7 +491,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual T getValue () const {
|
virtual T getValue () const {
|
||||||
if (_getter) return (*_getter)();
|
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.
|
* Create a copy of this raw value, bound to the same functions.
|
||||||
*/
|
*/
|
||||||
virtual SGRawValue<T> * clone () const {
|
virtual SGRaw* clone () const {
|
||||||
return new SGRawValueFunctions<T>(_getter,_setter);
|
return new SGRawValueFunctions(_getter,_setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -353,14 +540,14 @@ public:
|
|||||||
virtual ~SGRawValueFunctionsIndexed () {}
|
virtual ~SGRawValueFunctionsIndexed () {}
|
||||||
virtual T getValue () const {
|
virtual T getValue () const {
|
||||||
if (_getter) return (*_getter)(_index);
|
if (_getter) return (*_getter)(_index);
|
||||||
else return SGRawValue<T>::DefaultValue;
|
else return SGRawValue<T>::DefaultValue();
|
||||||
}
|
}
|
||||||
virtual bool setValue (T value) {
|
virtual bool setValue (T value) {
|
||||||
if (_setter) { (*_setter)(_index, value); return true; }
|
if (_setter) { (*_setter)(_index, value); return true; }
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
virtual SGRawValue<T> * clone () const {
|
virtual SGRaw* clone () const {
|
||||||
return new SGRawValueFunctionsIndexed<T>(_index, _getter, _setter);
|
return new SGRawValueFunctionsIndexed(_index, _getter, _setter);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
int _index;
|
int _index;
|
||||||
@@ -386,14 +573,14 @@ public:
|
|||||||
virtual ~SGRawValueMethods () {}
|
virtual ~SGRawValueMethods () {}
|
||||||
virtual T getValue () const {
|
virtual T getValue () const {
|
||||||
if (_getter) { return (_obj.*_getter)(); }
|
if (_getter) { return (_obj.*_getter)(); }
|
||||||
else { return SGRawValue<T>::DefaultValue; }
|
else { return SGRawValue<T>::DefaultValue(); }
|
||||||
}
|
}
|
||||||
virtual bool setValue (T value) {
|
virtual bool setValue (T value) {
|
||||||
if (_setter) { (_obj.*_setter)(value); return true; }
|
if (_setter) { (_obj.*_setter)(value); return true; }
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
virtual SGRawValue<T> * clone () const {
|
virtual SGRaw* clone () const {
|
||||||
return new SGRawValueMethods<C,T>(_obj, _getter, _setter);
|
return new SGRawValueMethods(_obj, _getter, _setter);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
C &_obj;
|
C &_obj;
|
||||||
@@ -420,14 +607,14 @@ public:
|
|||||||
virtual ~SGRawValueMethodsIndexed () {}
|
virtual ~SGRawValueMethodsIndexed () {}
|
||||||
virtual T getValue () const {
|
virtual T getValue () const {
|
||||||
if (_getter) { return (_obj.*_getter)(_index); }
|
if (_getter) { return (_obj.*_getter)(_index); }
|
||||||
else { return SGRawValue<T>::DefaultValue; }
|
else { return SGRawValue<T>::DefaultValue(); }
|
||||||
}
|
}
|
||||||
virtual bool setValue (T value) {
|
virtual bool setValue (T value) {
|
||||||
if (_setter) { (_obj.*_setter)(_index, value); return true; }
|
if (_setter) { (_obj.*_setter)(_index, value); return true; }
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
virtual SGRawValue<T> * clone () const {
|
virtual SGRaw* clone () const {
|
||||||
return new SGRawValueMethodsIndexed<C,T>(_obj, _index, _getter, _setter);
|
return new SGRawValueMethodsIndexed(_obj, _index, _getter, _setter);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
C &_obj;
|
C &_obj;
|
||||||
@@ -436,6 +623,77 @@ private:
|
|||||||
setter_t _setter;
|
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
|
* The smart pointer that manage reference counting
|
||||||
@@ -444,6 +702,11 @@ class SGPropertyNode;
|
|||||||
typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
|
typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
|
||||||
typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
|
typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
typedef std::vector<SGPropertyNode_ptr> PropertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The property change listener interface.
|
* The property change listener interface.
|
||||||
@@ -484,22 +747,6 @@ public:
|
|||||||
MAX_STRING_LEN = 1024
|
MAX_STRING_LEN = 1024
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Property value types.
|
|
||||||
*/
|
|
||||||
enum Type {
|
|
||||||
NONE = 0,
|
|
||||||
ALIAS,
|
|
||||||
BOOL,
|
|
||||||
INT,
|
|
||||||
LONG,
|
|
||||||
FLOAT,
|
|
||||||
DOUBLE,
|
|
||||||
STRING,
|
|
||||||
UNSPECIFIED
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access mode attributes.
|
* Access mode attributes.
|
||||||
*
|
*
|
||||||
@@ -550,7 +797,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Test whether this node contains a primitive leaf value.
|
* 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(); }
|
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.
|
* 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.
|
* 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);
|
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.
|
* Get a child node by name and index.
|
||||||
*/
|
*/
|
||||||
SGPropertyNode * getChild (const char * name, int index = 0,
|
SGPropertyNode * getChild (const char* name, int index = 0,
|
||||||
bool create = false);
|
bool create = false);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a child node by name and index.
|
|
||||||
*/
|
|
||||||
SGPropertyNode * getChild (const std::string& name, int index = 0,
|
SGPropertyNode * getChild (const std::string& name, int index = 0,
|
||||||
bool create = false)
|
bool create = false);
|
||||||
{ return getChild(name.c_str(), index, create); }
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a const child node by name and index.
|
* Get a const child node by name and index.
|
||||||
*/
|
*/
|
||||||
@@ -652,12 +900,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get a vector of all children with the specified name.
|
* 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.
|
* 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()); }
|
{ return getChildren(name.c_str()); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -682,15 +930,13 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Remove all children with the specified name.
|
* Remove all children with the specified name.
|
||||||
*/
|
*/
|
||||||
std::vector<SGPropertyNode_ptr> removeChildren (const char * name,
|
simgear::PropertyList removeChildren (const char * name, bool keep = true);
|
||||||
bool keep = true);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all children with the specified name.
|
* Remove all children with the specified name.
|
||||||
*/
|
*/
|
||||||
std::vector<SGPropertyNode_ptr> removeChildren (const std::string& name,
|
simgear::PropertyList removeChildren (const std::string& name,
|
||||||
bool keep = true)
|
bool keep = true)
|
||||||
{ return removeChildren(name.c_str(), keep); }
|
{ return removeChildren(name.c_str(), keep); }
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -725,7 +971,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Test whether the node's leaf value is aliased to another's.
|
* 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); }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -870,7 +1116,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get the type of leaf value, if any, for this node.
|
* 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;
|
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.
|
* Set a bool value for this node.
|
||||||
@@ -957,6 +1213,26 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool setUnspecifiedValue (const char * value);
|
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.
|
// Data binding.
|
||||||
@@ -968,42 +1244,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isTied () const { return _tied; }
|
bool isTied () const { return _tied; }
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
* Bind this node to an external source.
|
||||||
* Bind this node to an external bool source.
|
*/
|
||||||
*/
|
template<typename T>
|
||||||
bool tie (const SGRawValue<bool> &rawValue, bool useDefault = true);
|
bool tie(const SGRawValue<T> &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);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unbind this node from any external data source.
|
* Unbind this node from any external data source.
|
||||||
@@ -1020,12 +1265,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get another node's type.
|
* 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.
|
* 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()); }
|
{ 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 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.
|
* Set another node's value as a string.
|
||||||
*/
|
*/
|
||||||
bool setStringValue (const std::string& relative_path, const char * value)
|
bool setStringValue (const std::string& relative_path, const char * value)
|
||||||
{ return setStringValue(relative_path.c_str(), 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.
|
* Set another node's value with no specified type.
|
||||||
@@ -1323,7 +1573,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get the number of listeners.
|
* 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 ();
|
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:
|
protected:
|
||||||
|
|
||||||
@@ -1359,12 +1619,13 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* Protected constructor for making new nodes on demand.
|
* 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:
|
private:
|
||||||
|
|
||||||
// Get the raw value
|
// Get the raw value
|
||||||
bool get_bool () const;
|
bool get_bool () const;
|
||||||
int get_int () const;
|
int get_int () const;
|
||||||
long get_long () const;
|
long get_long () const;
|
||||||
@@ -1372,7 +1633,7 @@ private:
|
|||||||
double get_double () const;
|
double get_double () const;
|
||||||
const char * get_string () const;
|
const char * get_string () const;
|
||||||
|
|
||||||
// Set the raw value
|
// Set the raw value
|
||||||
bool set_bool (bool value);
|
bool set_bool (bool value);
|
||||||
bool set_int (int value);
|
bool set_int (int value);
|
||||||
bool set_long (long value);
|
bool set_long (long value);
|
||||||
@@ -1386,7 +1647,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
const char * make_string () const;
|
const char * make_string () const;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trace a read access.
|
* Trace a read access.
|
||||||
*/
|
*/
|
||||||
@@ -1409,29 +1669,23 @@ private:
|
|||||||
|
|
||||||
int _index;
|
int _index;
|
||||||
std::string _name;
|
std::string _name;
|
||||||
mutable std::string _display_name;
|
|
||||||
/// To avoid cyclic reference counting loops this shall not be a reference
|
/// To avoid cyclic reference counting loops this shall not be a reference
|
||||||
/// counted pointer
|
/// counted pointer
|
||||||
SGPropertyNode * _parent;
|
SGPropertyNode * _parent;
|
||||||
std::vector<SGPropertyNode_ptr> _children;
|
simgear::PropertyList _children;
|
||||||
std::vector<SGPropertyNode_ptr> _removedChildren;
|
simgear::PropertyList _removedChildren;
|
||||||
std::vector<hash_table *> _linkedNodes;
|
std::vector<hash_table *> _linkedNodes;
|
||||||
mutable std::string _path;
|
mutable std::string _path;
|
||||||
mutable std::string _buffer;
|
mutable std::string _buffer;
|
||||||
hash_table * _path_cache;
|
hash_table * _path_cache;
|
||||||
Type _type;
|
simgear::props::Type _type;
|
||||||
bool _tied;
|
bool _tied;
|
||||||
int _attr;
|
int _attr;
|
||||||
|
|
||||||
// The right kind of pointer...
|
// The right kind of pointer...
|
||||||
union {
|
union {
|
||||||
SGPropertyNode * alias;
|
SGPropertyNode * alias;
|
||||||
SGRawValue<bool> * bool_val;
|
SGRaw* val;
|
||||||
SGRawValue<int> * int_val;
|
|
||||||
SGRawValue<long> * long_val;
|
|
||||||
SGRawValue<float> * float_val;
|
|
||||||
SGRawValue<double> * double_val;
|
|
||||||
SGRawValue<const char *> * string_val;
|
|
||||||
} _value;
|
} _value;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
@@ -1447,8 +1701,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); }
|
void add_linked_node (hash_table * node) { _linkedNodes.push_back(node); }
|
||||||
bool remove_linked_node (hash_table * node);
|
bool remove_linked_node (hash_table * node);
|
||||||
|
|
||||||
@@ -1505,10 +1759,21 @@ private:
|
|||||||
unsigned int _data_length;
|
unsigned int _data_length;
|
||||||
bucket ** _data;
|
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>
|
template<typename T>
|
||||||
T getValue(const SGPropertyNode*);
|
T getValue(const SGPropertyNode*);
|
||||||
|
|
||||||
@@ -1574,6 +1839,169 @@ inline bool setValue (SGPropertyNode* node, const std::string& value)
|
|||||||
return node->setStringValue(value.c_str());
|
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
|
#endif // __PROPS_HXX
|
||||||
|
|
||||||
// end of props.hxx
|
// end of props.hxx
|
||||||
|
|||||||
+70
-33
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <simgear/sg_inlines.h>
|
#include <simgear/sg_inlines.h>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
#include <simgear/math/SGMath.hxx>
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/xml/easyxml.hxx>
|
#include <simgear/xml/easyxml.hxx>
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstring> // strcmp()
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -52,8 +54,11 @@ class PropsVisitor : public XMLVisitor
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PropsVisitor (SGPropertyNode * root, const string &base, int default_mode = 0)
|
PropsVisitor (SGPropertyNode * root, const string &base, int default_mode = 0,
|
||||||
: _default_mode(default_mode), _root(root), _level(0), _base(base), _hasException(false) {}
|
bool extended = false)
|
||||||
|
: _default_mode(default_mode), _root(root), _level(0), _base(base),
|
||||||
|
_hasException(false), _extended(extended)
|
||||||
|
{}
|
||||||
|
|
||||||
virtual ~PropsVisitor () {}
|
virtual ~PropsVisitor () {}
|
||||||
|
|
||||||
@@ -110,6 +115,7 @@ private:
|
|||||||
string _base;
|
string _base;
|
||||||
sg_io_exception _exception;
|
sg_io_exception _exception;
|
||||||
bool _hasException;
|
bool _hasException;
|
||||||
|
bool _extended;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -167,7 +173,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
|
|||||||
SGPath path(SGPath(_base).dir());
|
SGPath path(SGPath(_base).dir());
|
||||||
path.append(attval);
|
path.append(attval);
|
||||||
try {
|
try {
|
||||||
readProperties(path.str(), _root);
|
readProperties(path.str(), _root, 0, _extended);
|
||||||
} catch (sg_io_exception &e) {
|
} catch (sg_io_exception &e) {
|
||||||
setException(e);
|
setException(e);
|
||||||
}
|
}
|
||||||
@@ -181,16 +187,17 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
|
|||||||
// Get the index.
|
// Get the index.
|
||||||
attval = atts.getValue("n");
|
attval = atts.getValue("n");
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
string strName(name);
|
||||||
if (attval != 0) {
|
if (attval != 0) {
|
||||||
index = atoi(attval);
|
index = atoi(attval);
|
||||||
st.counters[name] = SG_MAX2(st.counters[name], index+1);
|
st.counters[strName] = SG_MAX2(st.counters[strName], index+1);
|
||||||
} else {
|
} else {
|
||||||
index = st.counters[name];
|
index = st.counters[strName];
|
||||||
st.counters[name]++;
|
st.counters[strName]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Got the index, so grab the node.
|
// 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)) {
|
if (!node->getAttribute(SGPropertyNode::WRITE)) {
|
||||||
SG_LOG(SG_INPUT, SG_ALERT, "Not overwriting write-protected property "
|
SG_LOG(SG_INPUT, SG_ALERT, "Not overwriting write-protected property "
|
||||||
<< node->getPath(true));
|
<< node->getPath(true));
|
||||||
@@ -235,7 +242,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
|
|||||||
SGPath path(SGPath(_base).dir());
|
SGPath path(SGPath(_base).dir());
|
||||||
path.append(attval);
|
path.append(attval);
|
||||||
try {
|
try {
|
||||||
readProperties(path.str(), node);
|
readProperties(path.str(), node, 0, _extended);
|
||||||
} catch (sg_io_exception &e) {
|
} catch (sg_io_exception &e) {
|
||||||
setException(e);
|
setException(e);
|
||||||
}
|
}
|
||||||
@@ -275,6 +282,12 @@ PropsVisitor::endElement (const char * name)
|
|||||||
ret = st.node->setDoubleValue(strtod(_data.c_str(), 0));
|
ret = st.node->setDoubleValue(strtod(_data.c_str(), 0));
|
||||||
} else if (st.type == "string") {
|
} else if (st.type == "string") {
|
||||||
ret = st.node->setStringValue(_data.c_str());
|
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") {
|
} else if (st.type == "unspecified") {
|
||||||
ret = st.node->setUnspecifiedValue(_data.c_str());
|
ret = st.node->setUnspecifiedValue(_data.c_str());
|
||||||
} else if (_level == 1) {
|
} else if (_level == 1) {
|
||||||
@@ -344,9 +357,9 @@ PropsVisitor::warning (const char * message, int line, int column)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
readProperties (istream &input, SGPropertyNode * start_node,
|
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);
|
readXML(input, visitor, base);
|
||||||
if (visitor.hasException())
|
if (visitor.hasException())
|
||||||
throw visitor.getException();
|
throw visitor.getException();
|
||||||
@@ -362,9 +375,9 @@ readProperties (istream &input, SGPropertyNode * start_node,
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
readProperties (const string &file, SGPropertyNode * start_node,
|
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);
|
readXML(file, visitor);
|
||||||
if (visitor.hasException())
|
if (visitor.hasException())
|
||||||
throw visitor.getException();
|
throw visitor.getException();
|
||||||
@@ -380,9 +393,10 @@ readProperties (const string &file, SGPropertyNode * start_node,
|
|||||||
* @return true if the read succeeded, false otherwise.
|
* @return true if the read succeeded, false otherwise.
|
||||||
*/
|
*/
|
||||||
void readProperties (const char *buf, const int size,
|
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);
|
readXML(buf, size, visitor);
|
||||||
if (visitor.hasException())
|
if (visitor.hasException())
|
||||||
throw visitor.getException();
|
throw visitor.getException();
|
||||||
@@ -399,26 +413,33 @@ void readProperties (const char *buf, const int size,
|
|||||||
* Return the type name.
|
* Return the type name.
|
||||||
*/
|
*/
|
||||||
static const char *
|
static const char *
|
||||||
getTypeName (SGPropertyNode::Type type)
|
getTypeName (simgear::props::Type type)
|
||||||
{
|
{
|
||||||
|
using namespace simgear;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SGPropertyNode::UNSPECIFIED:
|
case props::UNSPECIFIED:
|
||||||
return "unspecified";
|
return "unspecified";
|
||||||
case SGPropertyNode::BOOL:
|
case props::BOOL:
|
||||||
return "bool";
|
return "bool";
|
||||||
case SGPropertyNode::INT:
|
case props::INT:
|
||||||
return "int";
|
return "int";
|
||||||
case SGPropertyNode::LONG:
|
case props::LONG:
|
||||||
return "long";
|
return "long";
|
||||||
case SGPropertyNode::FLOAT:
|
case props::FLOAT:
|
||||||
return "float";
|
return "float";
|
||||||
case SGPropertyNode::DOUBLE:
|
case props::DOUBLE:
|
||||||
return "double";
|
return "double";
|
||||||
case SGPropertyNode::STRING:
|
case props::STRING:
|
||||||
return "string";
|
return "string";
|
||||||
case SGPropertyNode::ALIAS:
|
case props::VEC3D:
|
||||||
case SGPropertyNode::NONE:
|
return "vec3d";
|
||||||
|
case props::VEC4D:
|
||||||
|
return "vec4d";
|
||||||
|
case props::ALIAS:
|
||||||
|
case props::NONE:
|
||||||
return "unspecified";
|
return "unspecified";
|
||||||
|
default: // avoid compiler warning
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep the compiler from squawking
|
// keep the compiler from squawking
|
||||||
@@ -524,7 +545,7 @@ writeNode (ostream &output, const SGPropertyNode * node,
|
|||||||
output << " alias=\"" << node->getAliasTarget()->getPath()
|
output << " alias=\"" << node->getAliasTarget()->getPath()
|
||||||
<< "\"/>" << endl;
|
<< "\"/>" << endl;
|
||||||
} else {
|
} else {
|
||||||
if (node->getType() != SGPropertyNode::UNSPECIFIED)
|
if (node->getType() != simgear::props::UNSPECIFIED)
|
||||||
output << " type=\"" << getTypeName(node->getType()) << '"';
|
output << " type=\"" << getTypeName(node->getType()) << '"';
|
||||||
output << '>';
|
output << '>';
|
||||||
writeData(output, node->getStringValue());
|
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
|
bool
|
||||||
copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
|
copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
|
||||||
{
|
{
|
||||||
|
using namespace simgear;
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
|
|
||||||
// First, copy the actual value,
|
// First, copy the actual value,
|
||||||
// if any.
|
// if any.
|
||||||
if (in->hasValue()) {
|
if (in->hasValue()) {
|
||||||
switch (in->getType()) {
|
switch (in->getType()) {
|
||||||
case SGPropertyNode::BOOL:
|
case props::BOOL:
|
||||||
if (!out->setBoolValue(in->getBoolValue()))
|
if (!out->setBoolValue(in->getBoolValue()))
|
||||||
retval = false;
|
retval = false;
|
||||||
break;
|
break;
|
||||||
case SGPropertyNode::INT:
|
case props::INT:
|
||||||
if (!out->setIntValue(in->getIntValue()))
|
if (!out->setIntValue(in->getIntValue()))
|
||||||
retval = false;
|
retval = false;
|
||||||
break;
|
break;
|
||||||
case SGPropertyNode::LONG:
|
case props::LONG:
|
||||||
if (!out->setLongValue(in->getLongValue()))
|
if (!out->setLongValue(in->getLongValue()))
|
||||||
retval = false;
|
retval = false;
|
||||||
break;
|
break;
|
||||||
case SGPropertyNode::FLOAT:
|
case props::FLOAT:
|
||||||
if (!out->setFloatValue(in->getFloatValue()))
|
if (!out->setFloatValue(in->getFloatValue()))
|
||||||
retval = false;
|
retval = false;
|
||||||
break;
|
break;
|
||||||
case SGPropertyNode::DOUBLE:
|
case props::DOUBLE:
|
||||||
if (!out->setDoubleValue(in->getDoubleValue()))
|
if (!out->setDoubleValue(in->getDoubleValue()))
|
||||||
retval = false;
|
retval = false;
|
||||||
break;
|
break;
|
||||||
case SGPropertyNode::STRING:
|
case props::STRING:
|
||||||
if (!out->setStringValue(in->getStringValue()))
|
if (!out->setStringValue(in->getStringValue()))
|
||||||
retval = false;
|
retval = false;
|
||||||
break;
|
break;
|
||||||
case SGPropertyNode::UNSPECIFIED:
|
case props::UNSPECIFIED:
|
||||||
if (!out->setUnspecifiedValue(in->getStringValue()))
|
if (!out->setUnspecifiedValue(in->getStringValue()))
|
||||||
retval = false;
|
retval = false;
|
||||||
break;
|
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:
|
default:
|
||||||
if (in->isAlias())
|
if (in->isAlias())
|
||||||
break;
|
break;
|
||||||
@@ -649,7 +686,7 @@ copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
|
|||||||
int nChildren = in->nChildren();
|
int nChildren = in->nChildren();
|
||||||
for (int i = 0; i < nChildren; i++) {
|
for (int i = 0; i < nChildren; i++) {
|
||||||
const SGPropertyNode * in_child = in->getChild(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(),
|
in_child->getIndex(),
|
||||||
true);
|
true);
|
||||||
if (!copyProperties(in_child, out_child))
|
if (!copyProperties(in_child, out_child))
|
||||||
|
|||||||
@@ -26,21 +26,23 @@
|
|||||||
* Read properties from an XML input stream.
|
* Read properties from an XML input stream.
|
||||||
*/
|
*/
|
||||||
void readProperties (std::istream &input, SGPropertyNode * start_node,
|
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.
|
* Read properties from an XML file.
|
||||||
*/
|
*/
|
||||||
void readProperties (const std::string &file, SGPropertyNode * start_node,
|
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.
|
* Read properties from an in-memory buffer.
|
||||||
*/
|
*/
|
||||||
void readProperties (const char *buf, const int size,
|
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;
|
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)
|
int main (int ac, char ** av)
|
||||||
{
|
{
|
||||||
@@ -342,5 +362,7 @@ int main (int ac, char ** av)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_addChild();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,4 +31,5 @@ routetest_LDADD = \
|
|||||||
libsgroute.a \
|
libsgroute.a \
|
||||||
$(top_builddir)/simgear/math/libsgmath.a \
|
$(top_builddir)/simgear/math/libsgmath.a \
|
||||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||||
|
$(top_builddir)/simgear/structure/libsgstructure.a \
|
||||||
$(base_LIBS)
|
$(base_LIBS)
|
||||||
|
|||||||
+26
-44
@@ -20,6 +20,9 @@
|
|||||||
//
|
//
|
||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <simgear_config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <plib/sg.h>
|
#include <plib/sg.h>
|
||||||
|
|
||||||
@@ -38,51 +41,22 @@ SGRoute::SGRoute() {
|
|||||||
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 */
|
/** 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 ];
|
SGWayPoint& curr = route[ index ];
|
||||||
double course, dist;
|
double course, dist;
|
||||||
|
|
||||||
if ( index == 0 ) {
|
if ( index == 0 ) {
|
||||||
dist = 0;
|
dist = 0;
|
||||||
} else {
|
course = 0.0;
|
||||||
const SGWayPoint& prev = route[ index - 1 ];
|
} else {
|
||||||
curr.CourseAndDistance( prev, &course, &dist );
|
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 {
|
} else {
|
||||||
route.insert( route.begin() + n, 1, wp );
|
route.insert( route.begin() + n, 1, wp );
|
||||||
// update distance of next leg if not at end of route
|
// 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) */
|
/** 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 );
|
route.erase( route.begin() + n );
|
||||||
// update distance of next leg if not at end of route
|
// update distance of next leg if not at end of route
|
||||||
if ( n < size - 1 )
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-6
@@ -52,7 +52,7 @@ private:
|
|||||||
route_list route;
|
route_list route;
|
||||||
int current_wp;
|
int current_wp;
|
||||||
|
|
||||||
void update_distance(int index);
|
void update_distance_and_track(int index);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -103,6 +103,22 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
* Set the current waypoint
|
||||||
* @param number of waypoint to make current.
|
* @param number of waypoint to make current.
|
||||||
@@ -113,6 +129,10 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int current_index() const {
|
||||||
|
return current_wp;
|
||||||
|
}
|
||||||
|
|
||||||
/** Increment the current waypoint pointer. */
|
/** Increment the current waypoint pointer. */
|
||||||
inline void increment_current() {
|
inline void increment_current() {
|
||||||
if ( current_wp < (int)route.size() - 1 ) {
|
if ( current_wp < (int)route.size() - 1 ) {
|
||||||
@@ -140,12 +160,9 @@ public:
|
|||||||
void delete_waypoint( int n = 0 );
|
void delete_waypoint( int n = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate perpendicular distance from the current route segment
|
* Helper, sum the distance members of each waypoint
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
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()
|
int main()
|
||||||
{
|
{
|
||||||
SGRoute route;
|
SGRoute route;
|
||||||
|
/*
|
||||||
route.add_waypoint( SGWayPoint(0, 0, 0, SGWayPoint::CARTESIAN, "Start") );
|
route.add_waypoint( SGWayPoint(0, 0, 0, SGWayPoint::CARTESIAN, "Start") );
|
||||||
route.add_waypoint( SGWayPoint(1, 0, 0, SGWayPoint::CARTESIAN, "1") );
|
route.add_waypoint( SGWayPoint(1, 0, 0, SGWayPoint::CARTESIAN, "1") );
|
||||||
route.add_waypoint( SGWayPoint(2, 0, 0, SGWayPoint::CARTESIAN, "2") );
|
route.add_waypoint( SGWayPoint(2, 0, 0, SGWayPoint::CARTESIAN, "2") );
|
||||||
@@ -48,6 +48,6 @@ int main()
|
|||||||
|
|
||||||
route.add_waypoint(wp2, 3);
|
route.add_waypoint(wp2, 3);
|
||||||
dump_route(route, "added back WP2 after WP3");
|
dump_route(route, "added back WP2 after WP3");
|
||||||
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-32
@@ -29,23 +29,38 @@
|
|||||||
|
|
||||||
#include "waypoint.hxx"
|
#include "waypoint.hxx"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
SGWayPoint::SGWayPoint( const double lon, const double lat, const double alt,
|
SGWayPoint::SGWayPoint( const double lon, const double lat, const double alt,
|
||||||
const modetype m, const string& s, const string& n ) {
|
const modetype, const string& s, const string& n ) :
|
||||||
target_lon = lon;
|
pos(SGGeod::fromDegM(lon, lat, alt)),
|
||||||
target_lat = lat;
|
id(s),
|
||||||
target_alt = alt;
|
name(n),
|
||||||
mode = m;
|
_distance(0.0),
|
||||||
id = s;
|
_track(0.0),
|
||||||
name = n;
|
_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
|
// Destructor
|
||||||
SGWayPoint::~SGWayPoint() {
|
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
|
// Calculate course and distances. For WGS84 and SPHERICAL
|
||||||
// coordinates lat, lon, and course are in degrees, alt and distance
|
// 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_lat,
|
||||||
const double cur_alt,
|
const double cur_alt,
|
||||||
double *course, double *dist ) const {
|
double *course, double *dist ) const {
|
||||||
if ( mode == WGS84 ) {
|
CourseAndDistance(SGGeod::fromDegM(cur_lon, cur_lat, cur_alt), *course, *dist);
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate course and distances between two waypoints
|
// Calculate course and distances between two waypoints
|
||||||
void SGWayPoint::CourseAndDistance( const SGWayPoint &wp,
|
void SGWayPoint::CourseAndDistance( const SGWayPoint &wp,
|
||||||
double *course, double *dist ) const {
|
double *course, double *dist ) const {
|
||||||
CourseAndDistance( wp.get_target_lon(),
|
CourseAndDistance( wp.get_target(), *course, *dist );
|
||||||
wp.get_target_lat(),
|
|
||||||
wp.get_target_alt(),
|
|
||||||
course, dist );
|
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-32
@@ -27,17 +27,12 @@
|
|||||||
#ifndef _WAYPOINT_HXX
|
#ifndef _WAYPOINT_HXX
|
||||||
#define _WAYPOINT_HXX
|
#define _WAYPOINT_HXX
|
||||||
|
|
||||||
|
|
||||||
#ifndef __cplusplus
|
|
||||||
# error This library requires C++
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
#include <string>
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
#include <simgear/math/SGGeod.hxx>
|
||||||
|
|
||||||
using std::string;
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,26 +52,20 @@ public:
|
|||||||
* the world is a perfect sphere. This is less compuntationally
|
* the world is a perfect sphere. This is less compuntationally
|
||||||
* expensive than using wgs84 math and still a fairly good
|
* expensive than using wgs84 math and still a fairly good
|
||||||
* approximation of the real world, especially over shorter distances.
|
* 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 {
|
enum modetype {
|
||||||
WGS84 = 0,
|
WGS84 = 0,
|
||||||
SPHERICAL = 1,
|
|
||||||
CARTESIAN = 2
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SGGeod pos;
|
||||||
|
std::string id;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
modetype mode;
|
// route data associated with the waypoint
|
||||||
|
double _distance;
|
||||||
double target_lon;
|
double _track;
|
||||||
double target_lat;
|
double _speed;
|
||||||
double target_alt;
|
|
||||||
double distance;
|
|
||||||
|
|
||||||
string id;
|
|
||||||
string name;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -91,7 +80,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
SGWayPoint( const double lon = 0.0, const double lat = 0.0,
|
SGWayPoint( const double lon = 0.0, const double lat = 0.0,
|
||||||
const double alt = 0.0, const modetype m = WGS84,
|
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 */
|
/** Destructor */
|
||||||
~SGWayPoint();
|
~SGWayPoint();
|
||||||
@@ -112,6 +106,9 @@ public:
|
|||||||
const double cur_alt,
|
const double cur_alt,
|
||||||
double *course, double *dist ) const;
|
double *course, double *dist ) const;
|
||||||
|
|
||||||
|
void CourseAndDistance(const SGGeod& current,
|
||||||
|
double& course, double& dist ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate course and distances between a specified starting waypoint
|
* Calculate course and distances between a specified starting waypoint
|
||||||
* and this waypoint.
|
* and this waypoint.
|
||||||
@@ -122,17 +119,16 @@ public:
|
|||||||
void CourseAndDistance( const SGWayPoint &wp,
|
void CourseAndDistance( const SGWayPoint &wp,
|
||||||
double *course, double *dist ) const;
|
double *course, double *dist ) const;
|
||||||
|
|
||||||
/** @return waypoint mode */
|
|
||||||
inline modetype get_mode() const { return mode; }
|
|
||||||
|
|
||||||
/** @return waypoint longitude */
|
/** @return waypoint longitude */
|
||||||
inline double get_target_lon() const { return target_lon; }
|
inline double get_target_lon() const { return pos.getLongitudeDeg(); }
|
||||||
|
|
||||||
/** @return waypoint latitude */
|
/** @return waypoint latitude */
|
||||||
inline double get_target_lat() const { return target_lat; }
|
inline double get_target_lat() const { return pos.getLatitudeDeg(); }
|
||||||
|
|
||||||
/** @return waypoint altitude */
|
/** @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; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This value is not calculated by this class. It is simply a
|
* This value is not calculated by this class. It is simply a
|
||||||
@@ -144,19 +140,25 @@ public:
|
|||||||
* is for your convenience only.
|
* is for your convenience only.
|
||||||
* @return waypoint distance holder (what ever the user has stashed here)
|
* @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.
|
* Set the waypoint distance value to a value of our choice.
|
||||||
* @param d distance
|
* @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 */
|
/** @return waypoint id */
|
||||||
inline const string& get_id() const { return id; }
|
inline const std::string& get_id() const { return id; }
|
||||||
|
|
||||||
/** @return waypoint name */
|
/** @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() {
|
int main() {
|
||||||
SGWayPoint a1(-93.216923, 44.880547, 0.0, SGWayPoint::WGS84, "KMSP");
|
SGWayPoint a1(-93.216923, 44.880547, 0.0, SGWayPoint::WGS84, "KMSP");
|
||||||
SGWayPoint a2(-93.216923, 44.880547, 0.0, SGWayPoint::SPHERICAL, "KMSP");
|
|
||||||
|
|
||||||
// KMSN (Madison)
|
// KMSN (Madison)
|
||||||
double cur_lon = -89.336939;
|
double cur_lon = -89.336939;
|
||||||
@@ -24,43 +24,15 @@ int main() {
|
|||||||
cout << "Distance to " << a1.get_id() << " is " << distance * SG_METER_TO_NM
|
cout << "Distance to " << a1.get_id() << " is " << distance * SG_METER_TO_NM
|
||||||
<< endl;
|
<< 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 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 );
|
b1.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||||
cout << "Course to " << b1.get_id() << " is " << course << endl;
|
cout << "Course to " << b1.get_id() << " is " << course << endl;
|
||||||
cout << "Distance to " << b1.get_id() << " is " << distance * SG_METER_TO_NM
|
cout << "Distance to " << b1.get_id() << " is " << distance * SG_METER_TO_NM
|
||||||
<< endl;
|
<< 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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
includedir = @includedir@/scene
|
includedir = @includedir@/scene
|
||||||
|
|
||||||
SUBDIRS = material model sky tgdb util
|
SUBDIRS = bvh material model sky tgdb util
|
||||||
|
|
||||||
# lib_LIBRARIES = libsgscene.a
|
# 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(triangle.getVertex(0).osg());
|
||||||
|
vertices->push_back(triangle.getVertex(1).osg());
|
||||||
|
vertices->push_back(triangle.getVertex(2).osg());
|
||||||
|
|
||||||
|
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(SGVec3f(sphere.getCenter()).osg());
|
||||||
|
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(bbv.getBox().getCenter().osg());
|
||||||
|
shape->setHalfLengths((0.5*bbv.getBox().getSize()).osg());
|
||||||
|
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
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "BVHLineGeometry.hxx"
|
||||||
|
|
||||||
|
#include "BVHVisitor.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
BVHLineGeometry::BVHLineGeometry(const SGLineSegmentf& lineSegment, Type type) :
|
||||||
|
_lineSegment(lineSegment),
|
||||||
|
_type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHLineGeometry::~BVHLineGeometry()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHLineGeometry::accept(BVHVisitor& visitor)
|
||||||
|
{
|
||||||
|
visitor.apply(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SGSphered
|
||||||
|
BVHLineGeometry::computeBoundingSphere() const
|
||||||
|
{
|
||||||
|
SGSphered sphere;
|
||||||
|
sphere.expandBy(SGVec3d(_lineSegment.getStart()));
|
||||||
|
sphere.expandBy(SGVec3d(_lineSegment.getEnd()));
|
||||||
|
return sphere;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// 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 BVHLineGeometry_hxx
|
||||||
|
#define BVHLineGeometry_hxx
|
||||||
|
|
||||||
|
#include <simgear/math/SGGeometry.hxx>
|
||||||
|
#include "BVHNode.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
class BVHLineGeometry : public BVHNode {
|
||||||
|
public:
|
||||||
|
enum Type {
|
||||||
|
CarrierCatapult,
|
||||||
|
CarrierWire
|
||||||
|
};
|
||||||
|
|
||||||
|
BVHLineGeometry(const SGLineSegmentf& lineSegment, Type type);
|
||||||
|
virtual ~BVHLineGeometry();
|
||||||
|
|
||||||
|
virtual void accept(BVHVisitor& visitor);
|
||||||
|
|
||||||
|
const SGLineSegmentf& getLineSegment() const
|
||||||
|
{ return _lineSegment; }
|
||||||
|
|
||||||
|
Type getType() const
|
||||||
|
{ return _type; }
|
||||||
|
|
||||||
|
virtual SGSphered computeBoundingSphere() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SGLineSegmentf _lineSegment;
|
||||||
|
Type _type;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <simgear/math/SGMath.hxx>
|
||||||
|
#include "BVHLineSegmentVisitor.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 "BVHStaticGeometry.hxx"
|
||||||
|
|
||||||
|
#include "BVHStaticData.hxx"
|
||||||
|
|
||||||
|
#include "BVHStaticNode.hxx"
|
||||||
|
#include "BVHStaticTriangle.hxx"
|
||||||
|
#include "BVHStaticBinary.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHLineSegmentVisitor::apply(BVHGroup& group)
|
||||||
|
{
|
||||||
|
if (!intersects(_lineSegment, group.getBoundingSphere()))
|
||||||
|
return;
|
||||||
|
group.traverse(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHLineSegmentVisitor::apply(BVHTransform& transform)
|
||||||
|
{
|
||||||
|
if (!intersects(_lineSegment, transform.getBoundingSphere()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool haveHit = _haveHit;
|
||||||
|
_haveHit = false;
|
||||||
|
|
||||||
|
// Push the line segment
|
||||||
|
SGLineSegmentd lineSegment = getLineSegment();
|
||||||
|
_lineSegment = transform.lineSegmentToLocal(lineSegment);
|
||||||
|
|
||||||
|
transform.traverse(*this);
|
||||||
|
|
||||||
|
if (_haveHit) {
|
||||||
|
_linearVelocity = transform.vecToWorld(_linearVelocity);
|
||||||
|
_angularVelocity = transform.vecToWorld(_angularVelocity);
|
||||||
|
SGVec3d point(transform.ptToWorld(_lineSegment.getEnd()));
|
||||||
|
_lineSegment.set(lineSegment.getStart(), point);
|
||||||
|
_normal = transform.vecToWorld(_normal);
|
||||||
|
} else {
|
||||||
|
_lineSegment = lineSegment;
|
||||||
|
_haveHit = haveHit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHLineSegmentVisitor::apply(BVHMotionTransform& transform)
|
||||||
|
{
|
||||||
|
if (!intersects(_lineSegment, transform.getBoundingSphere()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool haveHit = _haveHit;
|
||||||
|
_haveHit = false;
|
||||||
|
|
||||||
|
// Push the line segment
|
||||||
|
SGLineSegmentd lineSegment = getLineSegment();
|
||||||
|
SGMatrixd toLocal = transform.getToLocalTransform(_time);
|
||||||
|
_lineSegment = lineSegment.transform(toLocal);
|
||||||
|
|
||||||
|
transform.traverse(*this);
|
||||||
|
|
||||||
|
if (_haveHit) {
|
||||||
|
SGMatrixd toWorld = transform.getToWorldTransform(_time);
|
||||||
|
SGVec3d localStart = _lineSegment.getStart();
|
||||||
|
_linearVelocity += transform.getLinearVelocityAt(localStart);
|
||||||
|
_angularVelocity += transform.getAngularVelocity();
|
||||||
|
_linearVelocity = toWorld.xformVec(_linearVelocity);
|
||||||
|
_angularVelocity = toWorld.xformVec(_angularVelocity);
|
||||||
|
SGVec3d localEnd = _lineSegment.getEnd();
|
||||||
|
_lineSegment.set(lineSegment.getStart(), toWorld.xformPt(localEnd));
|
||||||
|
_normal = toWorld.xformVec(_normal);
|
||||||
|
if (!_id)
|
||||||
|
_id = transform.getId();
|
||||||
|
} else {
|
||||||
|
_lineSegment = lineSegment;
|
||||||
|
_haveHit = haveHit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHLineSegmentVisitor::apply(BVHLineGeometry&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHLineSegmentVisitor::apply(BVHStaticGeometry& node)
|
||||||
|
{
|
||||||
|
if (!intersects(_lineSegment, node.getBoundingSphere()))
|
||||||
|
return;
|
||||||
|
node.traverse(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHLineSegmentVisitor::apply(const BVHStaticBinary& node,
|
||||||
|
const BVHStaticData& data)
|
||||||
|
{
|
||||||
|
if (!intersects(SGLineSegmentf(_lineSegment), node.getBoundingBox()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The first box to enter is the one the startpoint is in.
|
||||||
|
// this increases the probability, that on exit of that box we do not
|
||||||
|
// even need to walk the other one, since the line segment is
|
||||||
|
// then already short enough to not intersect the other one anymore.
|
||||||
|
node.traverse(*this, data, _lineSegment.getStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHLineSegmentVisitor::apply(const BVHStaticTriangle& triangle,
|
||||||
|
const BVHStaticData& data)
|
||||||
|
{
|
||||||
|
SGTrianglef tri = triangle.getTriangle(data);
|
||||||
|
SGVec3f point;
|
||||||
|
if (!intersects(point, tri, SGLineSegmentf(_lineSegment), 1e-4f))
|
||||||
|
return;
|
||||||
|
setLineSegmentEnd(SGVec3d(point));
|
||||||
|
_normal = SGVec3d(tri.getNormal());
|
||||||
|
_linearVelocity = SGVec3d::zeros();
|
||||||
|
_angularVelocity = SGVec3d::zeros();
|
||||||
|
_material = data.getMaterial(triangle.getMaterialIndex());
|
||||||
|
_id = 0;
|
||||||
|
_haveHit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
// 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 BVHLineSegmentVisitor_hxx
|
||||||
|
#define BVHLineSegmentVisitor_hxx
|
||||||
|
|
||||||
|
#include <simgear/math/SGGeometry.hxx>
|
||||||
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
#include <simgear/scene/material/mat.hxx>
|
||||||
|
|
||||||
|
#include "BVHVisitor.hxx"
|
||||||
|
#include "BVHNode.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
class BVHLineSegmentVisitor : public BVHVisitor {
|
||||||
|
public:
|
||||||
|
BVHLineSegmentVisitor(const SGLineSegmentd& lineSegment,
|
||||||
|
const double& t = 0) :
|
||||||
|
_lineSegment(lineSegment),
|
||||||
|
_time(t),
|
||||||
|
_material(0),
|
||||||
|
_id(0),
|
||||||
|
_haveHit(false)
|
||||||
|
{ }
|
||||||
|
virtual ~BVHLineSegmentVisitor()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool empty() const
|
||||||
|
{ return !_haveHit; }
|
||||||
|
|
||||||
|
const SGLineSegmentd& getLineSegment() const
|
||||||
|
{ return _lineSegment; }
|
||||||
|
|
||||||
|
SGVec3d getPoint() const
|
||||||
|
{ return _lineSegment.getEnd(); }
|
||||||
|
const SGVec3d& getNormal() const
|
||||||
|
{ return _normal; }
|
||||||
|
const SGVec3d& getLinearVelocity() const
|
||||||
|
{ return _linearVelocity; }
|
||||||
|
const SGVec3d& getAngularVelocity() const
|
||||||
|
{ return _angularVelocity; }
|
||||||
|
const SGMaterial* getMaterial() const
|
||||||
|
{ return _material; }
|
||||||
|
BVHNode::Id getId() const
|
||||||
|
{ return _id; }
|
||||||
|
|
||||||
|
virtual void apply(BVHGroup& group);
|
||||||
|
virtual void apply(BVHTransform& transform);
|
||||||
|
virtual void apply(BVHMotionTransform& transform);
|
||||||
|
virtual void apply(BVHLineGeometry&);
|
||||||
|
virtual void apply(BVHStaticGeometry& node);
|
||||||
|
|
||||||
|
virtual void apply(const BVHStaticBinary&, const BVHStaticData&);
|
||||||
|
virtual void apply(const BVHStaticTriangle&, const BVHStaticData&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setLineSegmentEnd(const SGVec3d& end)
|
||||||
|
{
|
||||||
|
// Ok, you need to make sure that the new end is in the previous
|
||||||
|
// direction and that the line segment is not enlarged by that call.
|
||||||
|
#ifndef _NDEBUG
|
||||||
|
// FIXME insert code to check this...
|
||||||
|
#endif
|
||||||
|
_lineSegment.set(_lineSegment.getStart(), end);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SGLineSegmentd _lineSegment;
|
||||||
|
double _time;
|
||||||
|
|
||||||
|
// belongs in a derived class
|
||||||
|
SGVec3d _normal;
|
||||||
|
SGVec3d _linearVelocity;
|
||||||
|
SGVec3d _angularVelocity;
|
||||||
|
const SGMaterial* _material;
|
||||||
|
BVHNode::Id _id;
|
||||||
|
|
||||||
|
bool _haveHit;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "BVHMotionTransform.hxx"
|
||||||
|
|
||||||
|
#include "BVHVisitor.hxx"
|
||||||
|
#include "BVHNode.hxx"
|
||||||
|
#include "BVHGroup.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
BVHMotionTransform::BVHMotionTransform() :
|
||||||
|
_toWorldReference(SGMatrixd::unit()),
|
||||||
|
_toLocalReference(SGMatrixd::unit()),
|
||||||
|
_toWorldAmplification(1),
|
||||||
|
_toLocalAmplification(1),
|
||||||
|
_linearVelocity(0, 0, 0),
|
||||||
|
_angularVelocity(0, 0, 0),
|
||||||
|
_referenceTime(0),
|
||||||
|
_startTime(0),
|
||||||
|
_endTime(0),
|
||||||
|
_id(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHMotionTransform::~BVHMotionTransform()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHMotionTransform::accept(BVHVisitor& visitor)
|
||||||
|
{
|
||||||
|
visitor.apply(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHMotionTransform::setTransform(const BVHMotionTransform& transform)
|
||||||
|
{
|
||||||
|
_toWorldReference = transform._toWorldReference;
|
||||||
|
_toLocalReference = transform._toLocalReference;
|
||||||
|
_toWorldAmplification = transform._toWorldAmplification;
|
||||||
|
_toLocalAmplification = transform._toLocalAmplification;
|
||||||
|
_linearVelocity = transform._linearVelocity;
|
||||||
|
_angularVelocity = transform._angularVelocity;
|
||||||
|
_referenceTime = transform._referenceTime;
|
||||||
|
_startTime = transform._startTime;
|
||||||
|
_endTime = transform._endTime;
|
||||||
|
_id = transform._id;
|
||||||
|
invalidateParentBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHMotionTransform::setToWorldTransform(const SGMatrixd& transform)
|
||||||
|
{
|
||||||
|
_toWorldReference = transform;
|
||||||
|
invert(_toLocalReference, transform);
|
||||||
|
updateAmplificationFactors();
|
||||||
|
invalidateParentBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHMotionTransform::setToLocalTransform(const SGMatrixd& transform)
|
||||||
|
{
|
||||||
|
_toLocalReference = transform;
|
||||||
|
invert(_toWorldReference, transform);
|
||||||
|
updateAmplificationFactors();
|
||||||
|
invalidateParentBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
SGSphered
|
||||||
|
BVHMotionTransform::computeBoundingSphere() const
|
||||||
|
{
|
||||||
|
SGSphered sphere(BVHGroup::computeBoundingSphere());
|
||||||
|
if (sphere.empty())
|
||||||
|
return sphere;
|
||||||
|
SGMatrixd toWorldStart = getToWorldTransform(_startTime);
|
||||||
|
SGVec3d centerStart = toWorldStart.xformPt(sphere.getCenter());
|
||||||
|
SGMatrixd toWorldEnd = getToWorldTransform(_endTime);
|
||||||
|
SGVec3d centerEnd = toWorldEnd.xformPt(sphere.getCenter());
|
||||||
|
double rad = 0.5*length(centerStart - centerEnd) + sphere.getRadius();
|
||||||
|
rad *= _toWorldAmplification;
|
||||||
|
return SGSphered(0.5*(centerStart + centerEnd), rad);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHMotionTransform::updateAmplificationFactors()
|
||||||
|
{
|
||||||
|
// Hmm, this is just a hint, true?
|
||||||
|
// But anyway, almost all transforms in a scenegraph will
|
||||||
|
// have them equal to 1 ...
|
||||||
|
double r = norm(_toWorldReference.xformVec(SGVec3d(1, 0, 0)));
|
||||||
|
r = std::max(r, norm(_toWorldReference.xformVec(SGVec3d(0, 1, 0))));
|
||||||
|
r = std::max(r, norm(_toWorldReference.xformVec(SGVec3d(0, 0, 1))));
|
||||||
|
_toWorldAmplification = r;
|
||||||
|
|
||||||
|
r = norm(_toLocalReference.xformVec(SGVec3d(1, 0, 0)));
|
||||||
|
r = std::max(r, norm(_toLocalReference.xformVec(SGVec3d(0, 1, 0))));
|
||||||
|
r = std::max(r, norm(_toLocalReference.xformVec(SGVec3d(0, 0, 1))));
|
||||||
|
_toLocalAmplification = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
// 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 BVHMotionTransform_hxx
|
||||||
|
#define BVHMotionTransform_hxx
|
||||||
|
|
||||||
|
#include "BVHVisitor.hxx"
|
||||||
|
#include "BVHNode.hxx"
|
||||||
|
#include "BVHGroup.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
class BVHMotionTransform : public BVHGroup {
|
||||||
|
public:
|
||||||
|
BVHMotionTransform();
|
||||||
|
virtual ~BVHMotionTransform();
|
||||||
|
|
||||||
|
virtual void accept(BVHVisitor& visitor);
|
||||||
|
|
||||||
|
void setTransform(const BVHMotionTransform& transform);
|
||||||
|
void setToWorldTransform(const SGMatrixd& transform);
|
||||||
|
void setToLocalTransform(const SGMatrixd& transform);
|
||||||
|
|
||||||
|
void setLinearVelocity(const SGVec3d& linearVelocity)
|
||||||
|
{ _linearVelocity = linearVelocity; }
|
||||||
|
const SGVec3d& getLinearVelocity() const
|
||||||
|
{ return _linearVelocity; }
|
||||||
|
|
||||||
|
void setAngularVelocity(const SGVec3d& angularVelocity)
|
||||||
|
{ _angularVelocity = angularVelocity; }
|
||||||
|
const SGVec3d& getAngularVelocity() const
|
||||||
|
{ return _angularVelocity; }
|
||||||
|
|
||||||
|
void setReferenceTime(const double& referenceTime)
|
||||||
|
{ _referenceTime = referenceTime; }
|
||||||
|
const double& getReferenceTime() const
|
||||||
|
{ return _referenceTime; }
|
||||||
|
|
||||||
|
void setStartTime(const double& startTime)
|
||||||
|
{ _startTime = startTime; }
|
||||||
|
const double& getStartTime() const
|
||||||
|
{ return _startTime; }
|
||||||
|
|
||||||
|
void setEndTime(const double& endTime)
|
||||||
|
{ _endTime = endTime; }
|
||||||
|
const double& getEndTime() const
|
||||||
|
{ return _endTime; }
|
||||||
|
|
||||||
|
SGMatrixd getToWorldTransform(const double& t) const
|
||||||
|
{
|
||||||
|
if (t == _referenceTime)
|
||||||
|
return _toWorldReference;
|
||||||
|
double dt = t - _referenceTime;
|
||||||
|
SGMatrixd matrix(_toWorldReference);
|
||||||
|
matrix.postMultRotate(SGQuatd::fromAngleAxis(dt*_angularVelocity));
|
||||||
|
matrix.postMultTranslate(dt*_linearVelocity);
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
SGMatrixd getToLocalTransform(const double& t) const
|
||||||
|
{
|
||||||
|
if (t == _referenceTime)
|
||||||
|
return _toLocalReference;
|
||||||
|
double dt = _referenceTime - t;
|
||||||
|
SGMatrixd matrix(_toLocalReference);
|
||||||
|
matrix.preMultRotate(SGQuatd::fromAngleAxis(dt*_angularVelocity));
|
||||||
|
matrix.preMultTranslate(dt*_linearVelocity);
|
||||||
|
return matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SGMatrixd& getToWorldReferenceTransform() const
|
||||||
|
{ return _toWorldReference; }
|
||||||
|
const SGMatrixd& getToLocalReferenceTransform() const
|
||||||
|
{ return _toLocalReference; }
|
||||||
|
|
||||||
|
SGVec3d getLinearVelocityAt(const SGVec3d& reference) const
|
||||||
|
{ return _linearVelocity + cross(_angularVelocity, reference); }
|
||||||
|
|
||||||
|
SGSphered sphereToLocal(const SGSphered& sphere, const double& t) const
|
||||||
|
{
|
||||||
|
SGMatrixd matrix = getToLocalTransform(t);
|
||||||
|
SGVec3d center = matrix.xformPt(sphere.getCenter());
|
||||||
|
double radius = _toLocalAmplification*sphere.getRadius();
|
||||||
|
return SGSphered(center, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setId(Id id)
|
||||||
|
{ _id = id; }
|
||||||
|
Id getId() const
|
||||||
|
{ return _id; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual SGSphered computeBoundingSphere() const;
|
||||||
|
void updateAmplificationFactors();
|
||||||
|
|
||||||
|
SGMatrixd _toWorldReference;
|
||||||
|
SGMatrixd _toLocalReference;
|
||||||
|
double _toWorldAmplification;
|
||||||
|
double _toLocalAmplification;
|
||||||
|
|
||||||
|
SGVec3d _linearVelocity;
|
||||||
|
SGVec3d _angularVelocity;
|
||||||
|
|
||||||
|
double _referenceTime;
|
||||||
|
double _startTime;
|
||||||
|
double _endTime;
|
||||||
|
|
||||||
|
Id _id;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
// 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 BVHNearestPointVisitor_hxx
|
||||||
|
#define BVHNearestPointVisitor_hxx
|
||||||
|
|
||||||
|
#include <simgear/math/SGGeometry.hxx>
|
||||||
|
|
||||||
|
#include "BVHVisitor.hxx"
|
||||||
|
|
||||||
|
#include "BVHNode.hxx"
|
||||||
|
#include "BVHGroup.hxx"
|
||||||
|
#include "BVHTransform.hxx"
|
||||||
|
#include "BVHLineGeometry.hxx"
|
||||||
|
#include "BVHStaticGeometry.hxx"
|
||||||
|
|
||||||
|
#include "BVHStaticData.hxx"
|
||||||
|
|
||||||
|
#include "BVHStaticNode.hxx"
|
||||||
|
#include "BVHStaticTriangle.hxx"
|
||||||
|
#include "BVHStaticBinary.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
class BVHNearestPointVisitor : public BVHVisitor {
|
||||||
|
public:
|
||||||
|
BVHNearestPointVisitor(const SGSphered& sphere, const double& t) :
|
||||||
|
_sphere(sphere),
|
||||||
|
_time(t),
|
||||||
|
_material(0),
|
||||||
|
_id(0),
|
||||||
|
_havePoint(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual void apply(BVHGroup& leaf)
|
||||||
|
{
|
||||||
|
if (!intersects(_sphere, leaf.getBoundingSphere()))
|
||||||
|
return;
|
||||||
|
leaf.traverse(*this);
|
||||||
|
}
|
||||||
|
virtual void apply(BVHTransform& transform)
|
||||||
|
{
|
||||||
|
if (!intersects(_sphere, transform.getBoundingSphere()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SGSphered sphere = _sphere;
|
||||||
|
_sphere = transform.sphereToLocal(sphere);
|
||||||
|
bool havePoint = _havePoint;
|
||||||
|
_havePoint = false;
|
||||||
|
|
||||||
|
transform.traverse(*this);
|
||||||
|
|
||||||
|
if (_havePoint) {
|
||||||
|
_point = transform.ptToWorld(_point);
|
||||||
|
_linearVelocity = transform.vecToWorld(_linearVelocity);
|
||||||
|
_angularVelocity = transform.vecToWorld(_angularVelocity);
|
||||||
|
}
|
||||||
|
_havePoint |= havePoint;
|
||||||
|
_sphere.setCenter(sphere.getCenter());
|
||||||
|
}
|
||||||
|
virtual void apply(BVHMotionTransform& transform)
|
||||||
|
{
|
||||||
|
if (!intersects(_sphere, transform.getBoundingSphere()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SGSphered sphere = _sphere;
|
||||||
|
_sphere = transform.sphereToLocal(sphere, _time);
|
||||||
|
bool havePoint = _havePoint;
|
||||||
|
_havePoint = false;
|
||||||
|
|
||||||
|
transform.traverse(*this);
|
||||||
|
|
||||||
|
if (_havePoint) {
|
||||||
|
SGMatrixd toWorld = transform.getToWorldTransform(_time);
|
||||||
|
SGVec3d localCenter = _sphere.getCenter();
|
||||||
|
_linearVelocity += transform.getLinearVelocityAt(localCenter);
|
||||||
|
_angularVelocity += transform.getAngularVelocity();
|
||||||
|
_linearVelocity = toWorld.xformVec(_linearVelocity);
|
||||||
|
_angularVelocity = toWorld.xformVec(_angularVelocity);
|
||||||
|
_point = toWorld.xformPt(_point);
|
||||||
|
if (!_id)
|
||||||
|
_id = transform.getId();
|
||||||
|
}
|
||||||
|
_havePoint |= havePoint;
|
||||||
|
_sphere.setCenter(sphere.getCenter());
|
||||||
|
}
|
||||||
|
virtual void apply(BVHLineGeometry& node)
|
||||||
|
{ }
|
||||||
|
virtual void apply(BVHStaticGeometry& node)
|
||||||
|
{
|
||||||
|
if (!intersects(_sphere, node.getBoundingSphere()))
|
||||||
|
return;
|
||||||
|
node.traverse(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
|
||||||
|
{
|
||||||
|
if (!intersects(_sphere, node.getBoundingBox()))
|
||||||
|
return;
|
||||||
|
node.traverse(*this, data, _sphere.getCenter());
|
||||||
|
}
|
||||||
|
virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
|
||||||
|
{
|
||||||
|
SGVec3f center(_sphere.getCenter());
|
||||||
|
SGVec3d closest(closestPoint(node.getTriangle(data), center));
|
||||||
|
if (!intersects(_sphere, closest))
|
||||||
|
return;
|
||||||
|
_point = closest;
|
||||||
|
_linearVelocity = SGVec3d::zeros();
|
||||||
|
_angularVelocity = SGVec3d::zeros();
|
||||||
|
_material = data.getMaterial(node.getMaterialIndex());
|
||||||
|
// The trick is to decrease the radius of the search sphere.
|
||||||
|
_sphere.setRadius(length(closest - _sphere.getCenter()));
|
||||||
|
_havePoint = true;
|
||||||
|
_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSphere(const SGSphered& sphere)
|
||||||
|
{ _sphere = sphere; }
|
||||||
|
const SGSphered& getSphere() const
|
||||||
|
{ return _sphere; }
|
||||||
|
|
||||||
|
const SGVec3d& getPoint() const
|
||||||
|
{ return _point; }
|
||||||
|
const SGVec3d& getLinearVelocity() const
|
||||||
|
{ return _linearVelocity; }
|
||||||
|
const SGVec3d& getAngularVelocity() const
|
||||||
|
{ return _angularVelocity; }
|
||||||
|
const SGMaterial* getMaterial() const
|
||||||
|
{ return _material; }
|
||||||
|
BVHNode::Id getId() const
|
||||||
|
{ return _id; }
|
||||||
|
|
||||||
|
bool empty() const
|
||||||
|
{ return !_havePoint; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SGSphered _sphere;
|
||||||
|
double _time;
|
||||||
|
|
||||||
|
SGVec3d _point;
|
||||||
|
SGVec3d _linearVelocity;
|
||||||
|
SGVec3d _angularVelocity;
|
||||||
|
const SGMaterial* _material;
|
||||||
|
BVHNode::Id _id;
|
||||||
|
|
||||||
|
bool _havePoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "BVHNode.hxx"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <simgear/structure/SGAtomic.hxx>
|
||||||
|
#include <simgear/math/SGGeometry.hxx>
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
BVHNode::BVHNode() :
|
||||||
|
_dirtyBoundingSphere(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHNode::~BVHNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHNode::Id
|
||||||
|
BVHNode::getNewId()
|
||||||
|
{
|
||||||
|
static SGAtomic id(0);
|
||||||
|
return ++id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHNode::addParent(BVHNode* parent)
|
||||||
|
{
|
||||||
|
// should not happen, but be paranoid ...
|
||||||
|
ParentList::iterator i;
|
||||||
|
i = std::find(_parents.begin(), _parents.end(), parent);
|
||||||
|
if (i != _parents.end())
|
||||||
|
return;
|
||||||
|
// add to the parents list ...
|
||||||
|
_parents.push_back(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHNode::removeParent(BVHNode* parent)
|
||||||
|
{
|
||||||
|
ParentList::iterator i;
|
||||||
|
i = std::find(_parents.begin(), _parents.end(), parent);
|
||||||
|
if (i == _parents.end())
|
||||||
|
return;
|
||||||
|
_parents.erase(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHNode::invalidateParentBound()
|
||||||
|
{
|
||||||
|
for (ParentList::iterator i = _parents.begin(); i != _parents.end(); ++i)
|
||||||
|
(*i)->invalidateBound();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHNode::invalidateBound()
|
||||||
|
{
|
||||||
|
if (_dirtyBoundingSphere)
|
||||||
|
return;
|
||||||
|
invalidateParentBound();
|
||||||
|
_dirtyBoundingSphere = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
// 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 BVHNode_hxx
|
||||||
|
#define BVHNode_hxx
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <simgear/math/SGGeometry.hxx>
|
||||||
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
class BVHGroup;
|
||||||
|
class BVHVisitor;
|
||||||
|
|
||||||
|
// Base for the tree nodes
|
||||||
|
class BVHNode : public SGReferenced {
|
||||||
|
public:
|
||||||
|
BVHNode();
|
||||||
|
virtual ~BVHNode();
|
||||||
|
|
||||||
|
// visitors ...
|
||||||
|
virtual void accept(BVHVisitor& visitor) = 0;
|
||||||
|
|
||||||
|
const SGSphered& getBoundingSphere() const
|
||||||
|
{
|
||||||
|
if (_dirtyBoundingSphere) {
|
||||||
|
_boundingSphere = computeBoundingSphere();
|
||||||
|
_dirtyBoundingSphere = false;
|
||||||
|
}
|
||||||
|
return _boundingSphere;
|
||||||
|
}
|
||||||
|
virtual SGSphered computeBoundingSphere() const = 0;
|
||||||
|
|
||||||
|
/// A unique id for some kind of BVHNodes.
|
||||||
|
/// Currently only motions transforms.
|
||||||
|
typedef unsigned Id;
|
||||||
|
|
||||||
|
// Factory to get a new id
|
||||||
|
static Id getNewId();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class BVHGroup;
|
||||||
|
void addParent(BVHNode* parent);
|
||||||
|
void removeParent(BVHNode* parent);
|
||||||
|
|
||||||
|
void invalidateParentBound();
|
||||||
|
virtual void invalidateBound();
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable bool _dirtyBoundingSphere;
|
||||||
|
mutable SGSphered _boundingSphere;
|
||||||
|
|
||||||
|
typedef std::vector<BVHNode*> ParentList;
|
||||||
|
ParentList _parents;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "BVHStaticBinary.hxx"
|
||||||
|
|
||||||
|
#include "BVHVisitor.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
BVHStaticBinary::BVHStaticBinary(unsigned splitAxis,
|
||||||
|
const BVHStaticNode* leftChild,
|
||||||
|
const BVHStaticNode* rightChild,
|
||||||
|
const SGBoxf& boundingBox) :
|
||||||
|
_splitAxis(splitAxis),
|
||||||
|
_leftChild(leftChild),
|
||||||
|
_rightChild(rightChild),
|
||||||
|
_boundingBox(boundingBox)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHStaticBinary::~BVHStaticBinary()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHStaticBinary::accept(BVHVisitor& visitor, const BVHStaticData& data) const
|
||||||
|
{
|
||||||
|
visitor.apply(*this, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// 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 BVHStaticBinary_hxx
|
||||||
|
#define BVHStaticBinary_hxx
|
||||||
|
|
||||||
|
#include <simgear/math/SGGeometry.hxx>
|
||||||
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
#include "BVHStaticNode.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
class BVHStaticBinary : public BVHStaticNode {
|
||||||
|
public:
|
||||||
|
BVHStaticBinary(unsigned splitAxis, const BVHStaticNode* leftChild,
|
||||||
|
const BVHStaticNode* rightChild, const SGBoxf& box);
|
||||||
|
virtual ~BVHStaticBinary();
|
||||||
|
virtual void accept(BVHVisitor& visitor, const BVHStaticData& data) const;
|
||||||
|
|
||||||
|
void traverse(BVHVisitor& visitor, const BVHStaticData& data) const
|
||||||
|
{
|
||||||
|
_leftChild->accept(visitor, data);
|
||||||
|
_rightChild->accept(visitor, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traverse call that first enters the child node that is potentially closer
|
||||||
|
// to the given point than the other.
|
||||||
|
template<typename T>
|
||||||
|
void traverse(BVHVisitor& visitor, const BVHStaticData& data,
|
||||||
|
const SGVec3<T>& pt) const
|
||||||
|
{
|
||||||
|
float center = 0.5f*(_boundingBox.getMin()[_splitAxis]
|
||||||
|
+ _boundingBox.getMax()[_splitAxis]);
|
||||||
|
if (pt[_splitAxis] < center) {
|
||||||
|
_leftChild->accept(visitor, data);
|
||||||
|
_rightChild->accept(visitor, data);
|
||||||
|
} else {
|
||||||
|
_rightChild->accept(visitor, data);
|
||||||
|
_leftChild->accept(visitor, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned getSplitAxis() const
|
||||||
|
{ return _splitAxis; }
|
||||||
|
|
||||||
|
const BVHStaticNode* getLeftChild() const
|
||||||
|
{ return _leftChild; }
|
||||||
|
const BVHStaticNode* getRightChild() const
|
||||||
|
{ return _rightChild; }
|
||||||
|
|
||||||
|
const SGBoxf& getBoundingBox() const
|
||||||
|
{ return _boundingBox; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Note the order of the members, this is to avoid padding
|
||||||
|
unsigned _splitAxis;
|
||||||
|
SGSharedPtr<const BVHStaticNode> _leftChild;
|
||||||
|
SGSharedPtr<const BVHStaticNode> _rightChild;
|
||||||
|
SGBoxf _boundingBox;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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 BVHStaticData_hxx
|
||||||
|
#define BVHStaticData_hxx
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
#include <simgear/math/SGGeometry.hxx>
|
||||||
|
|
||||||
|
/// FIXME, the SGMaterial class is too much tied to the scenegraph aspects of
|
||||||
|
/// the materials. Use some class more decribing the
|
||||||
|
/// nature of the surface we live on ...
|
||||||
|
class SGMaterial;
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
class BVHStaticData : public SGReferenced {
|
||||||
|
public:
|
||||||
|
virtual ~BVHStaticData() {}
|
||||||
|
|
||||||
|
unsigned addVertex(const SGVec3f& vertex)
|
||||||
|
{ _vertices.push_back(vertex); return _vertices.size() - 1; }
|
||||||
|
const SGVec3f& getVertex(unsigned i) const
|
||||||
|
{ return _vertices[i]; }
|
||||||
|
|
||||||
|
|
||||||
|
unsigned addMaterial(const SGMaterial* material)
|
||||||
|
{ _materials.push_back(material); return _materials.size() - 1; }
|
||||||
|
const SGMaterial* getMaterial(unsigned i) const
|
||||||
|
{ if (_materials.size() <= i) return 0; return _materials[i]; }
|
||||||
|
|
||||||
|
void trim()
|
||||||
|
{
|
||||||
|
std::vector<SGVec3f>(_vertices).swap(_vertices);
|
||||||
|
std::vector<const SGMaterial*>(_materials).swap(_materials);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<SGVec3f> _vertices;
|
||||||
|
std::vector<const SGMaterial*> _materials;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "BVHStaticGeometry.hxx"
|
||||||
|
|
||||||
|
#include "BVHBoundingBoxVisitor.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
BVHStaticGeometry::BVHStaticGeometry(const BVHStaticNode* staticNode,
|
||||||
|
const BVHStaticData* staticData) :
|
||||||
|
_staticNode(staticNode),
|
||||||
|
_staticData(staticData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHStaticGeometry::~BVHStaticGeometry()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BVHStaticGeometry::accept(BVHVisitor& visitor)
|
||||||
|
{
|
||||||
|
visitor.apply(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SGSphered
|
||||||
|
BVHStaticGeometry::computeBoundingSphere() const
|
||||||
|
{
|
||||||
|
BVHBoundingBoxVisitor bbv;
|
||||||
|
_staticNode->accept(bbv, *_staticData);
|
||||||
|
SGSphered sphere;
|
||||||
|
sphere.expandBy(SGBoxd(bbv.getBox()));
|
||||||
|
return sphere;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// 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 BVHStaticGeometry_hxx
|
||||||
|
#define BVHStaticGeometry_hxx
|
||||||
|
|
||||||
|
#include <simgear/math/SGGeometry.hxx>
|
||||||
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
|
||||||
|
#include "BVHVisitor.hxx"
|
||||||
|
#include "BVHNode.hxx"
|
||||||
|
#include "BVHStaticData.hxx"
|
||||||
|
#include "BVHStaticNode.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
class BVHStaticGeometry : public BVHNode {
|
||||||
|
public:
|
||||||
|
BVHStaticGeometry(const BVHStaticNode* staticNode,
|
||||||
|
const BVHStaticData* staticData);
|
||||||
|
virtual ~BVHStaticGeometry();
|
||||||
|
|
||||||
|
virtual void accept(BVHVisitor& visitor);
|
||||||
|
|
||||||
|
void traverse(BVHVisitor& visitor) const
|
||||||
|
{ _staticNode->accept(visitor, *_staticData); }
|
||||||
|
|
||||||
|
const BVHStaticData* getStaticData() const
|
||||||
|
{ return _staticData; }
|
||||||
|
const BVHStaticNode* getStaticNode() const
|
||||||
|
{ return _staticNode; }
|
||||||
|
|
||||||
|
virtual SGSphered computeBoundingSphere() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SGSharedPtr<const BVHStaticNode> _staticNode;
|
||||||
|
SGSharedPtr<const BVHStaticData> _staticData;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
// 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 BVHStaticGeometryBuilder_hxx
|
||||||
|
#define BVHStaticGeometryBuilder_hxx
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <simgear/structure/SGReferenced.hxx>
|
||||||
|
#include <simgear/structure/SGSharedPtr.hxx>
|
||||||
|
|
||||||
|
#include "BVHVisitor.hxx"
|
||||||
|
#include "BVHNode.hxx"
|
||||||
|
#include "BVHGroup.hxx"
|
||||||
|
#include "BVHTransform.hxx"
|
||||||
|
|
||||||
|
#include "BVHStaticData.hxx"
|
||||||
|
|
||||||
|
#include "BVHStaticNode.hxx"
|
||||||
|
#include "BVHStaticLeaf.hxx"
|
||||||
|
#include "BVHStaticTriangle.hxx"
|
||||||
|
#include "BVHStaticBinary.hxx"
|
||||||
|
#include "BVHStaticGeometry.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
class BVHStaticGeometryBuilder : public SGReferenced {
|
||||||
|
public:
|
||||||
|
BVHStaticGeometryBuilder() :
|
||||||
|
_staticData(new BVHStaticData),
|
||||||
|
_currentMaterial(0),
|
||||||
|
_currentMaterialIndex(~0u)
|
||||||
|
{ }
|
||||||
|
virtual ~BVHStaticGeometryBuilder()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
struct LeafRef {
|
||||||
|
LeafRef(const BVHStaticLeaf* leaf, const BVHStaticData& data) :
|
||||||
|
_leaf(leaf),
|
||||||
|
_box(_leaf->computeBoundingBox(data)),
|
||||||
|
_center(_leaf->computeCenter(data))
|
||||||
|
{ }
|
||||||
|
SGSharedPtr<const BVHStaticLeaf> _leaf;
|
||||||
|
SGBoxf _box;
|
||||||
|
SGVec3f _center;
|
||||||
|
};
|
||||||
|
typedef std::list<LeafRef> LeafRefList;
|
||||||
|
|
||||||
|
struct LeafRefLess : public std::binary_function<LeafRef, LeafRef, bool> {
|
||||||
|
LeafRefLess(unsigned sortAxis) : _sortAxis(sortAxis) {}
|
||||||
|
bool operator()(const LeafRef& x, const LeafRef& y)
|
||||||
|
{ return x._center[_sortAxis] < y._center[_sortAxis]; }
|
||||||
|
unsigned _sortAxis;
|
||||||
|
};
|
||||||
|
|
||||||
|
SGSharedPtr<BVHStaticData> _staticData;
|
||||||
|
LeafRefList _leafRefList;
|
||||||
|
|
||||||
|
typedef std::map<SGVec3f, unsigned> VertexMap;
|
||||||
|
VertexMap _vertexMap;
|
||||||
|
|
||||||
|
typedef std::set<SGVec3<unsigned> > TriangleSet;
|
||||||
|
TriangleSet _triangleSet;
|
||||||
|
|
||||||
|
void setCurrentMaterial(const SGMaterial* material)
|
||||||
|
{
|
||||||
|
_currentMaterial = material;
|
||||||
|
_currentMaterialIndex = addMaterial(material);
|
||||||
|
}
|
||||||
|
const SGMaterial* getCurrentMaterial() const
|
||||||
|
{
|
||||||
|
return _currentMaterial;
|
||||||
|
}
|
||||||
|
unsigned addMaterial(const SGMaterial* material)
|
||||||
|
{
|
||||||
|
MaterialMap::const_iterator i = _materialMap.find(material);
|
||||||
|
if (i != _materialMap.end())
|
||||||
|
return i->second;
|
||||||
|
unsigned index = _staticData->addMaterial(material);
|
||||||
|
_materialMap[material] = index;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef std::map<const SGMaterial*, unsigned> MaterialMap;
|
||||||
|
MaterialMap _materialMap;
|
||||||
|
const SGMaterial* _currentMaterial;
|
||||||
|
unsigned _currentMaterialIndex;
|
||||||
|
|
||||||
|
void addTriangle(const SGVec3f& v1, const SGVec3f& v2, const SGVec3f& v3)
|
||||||
|
{
|
||||||
|
unsigned indices[3] = { addVertex(v1), addVertex(v2), addVertex(v3) };
|
||||||
|
std::sort(indices, indices + 3);
|
||||||
|
SGVec3<unsigned> indexKey(indices);
|
||||||
|
if (_triangleSet.find(indexKey) != _triangleSet.end())
|
||||||
|
return;
|
||||||
|
_triangleSet.insert(indexKey);
|
||||||
|
BVHStaticTriangle* staticTriangle;
|
||||||
|
staticTriangle = new BVHStaticTriangle(_currentMaterialIndex, indices);
|
||||||
|
_leafRefList.push_back(LeafRef(staticTriangle, *_staticData));
|
||||||
|
}
|
||||||
|
unsigned addVertex(const SGVec3f& v)
|
||||||
|
{
|
||||||
|
VertexMap::const_iterator i = _vertexMap.find(v);
|
||||||
|
if (i != _vertexMap.end())
|
||||||
|
return i->second;
|
||||||
|
unsigned index = _staticData->addVertex(v);
|
||||||
|
_vertexMap[v] = index;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
BVHStaticGeometry* buildTree()
|
||||||
|
{
|
||||||
|
const BVHStaticNode* tree = buildTreeRecursive(_leafRefList);
|
||||||
|
if (!tree)
|
||||||
|
return 0;
|
||||||
|
_staticData->trim();
|
||||||
|
return new BVHStaticGeometry(tree, _staticData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void
|
||||||
|
centerSplitLeafs(unsigned splitAxis, const double& splitValue,
|
||||||
|
LeafRefList& leafs, LeafRefList split[2])
|
||||||
|
{
|
||||||
|
while (!leafs.empty()) {
|
||||||
|
if (leafs.front()._center[splitAxis] < splitValue) {
|
||||||
|
split[0].splice(split[0].begin(), leafs, leafs.begin());
|
||||||
|
} else {
|
||||||
|
split[1].splice(split[1].begin(), leafs, leafs.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
equalSplitLeafs(unsigned splitAxis, LeafRefList& leafs,
|
||||||
|
LeafRefList split[2])
|
||||||
|
{
|
||||||
|
leafs.sort(LeafRefLess(splitAxis));
|
||||||
|
while (true) {
|
||||||
|
if (leafs.empty())
|
||||||
|
break;
|
||||||
|
split[0].splice(split[0].begin(), leafs, leafs.begin());
|
||||||
|
|
||||||
|
if (leafs.empty())
|
||||||
|
break;
|
||||||
|
split[1].splice(split[1].begin(), leafs, --leafs.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const BVHStaticNode* buildTreeRecursive(LeafRefList& leafs)
|
||||||
|
{
|
||||||
|
// recursion termination
|
||||||
|
if (leafs.empty())
|
||||||
|
return 0;
|
||||||
|
// FIXME size is O(n)!!!
|
||||||
|
// if (leafs.size() == 1)
|
||||||
|
if (++leafs.begin() == leafs.end())
|
||||||
|
return leafs.front()._leaf;
|
||||||
|
|
||||||
|
SGBoxf box;
|
||||||
|
for (LeafRefList::const_iterator i = leafs.begin();
|
||||||
|
i != leafs.end(); ++i)
|
||||||
|
box.expandBy(i->_box);
|
||||||
|
|
||||||
|
// // FIXME ...
|
||||||
|
// if (length(box.getSize()) < 1)
|
||||||
|
// return new BVHBox(box);
|
||||||
|
|
||||||
|
if (box.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unsigned splitAxis = box.getBroadestAxis();
|
||||||
|
LeafRefList splitLeafs[2];
|
||||||
|
double splitValue = box.getCenter()[splitAxis];
|
||||||
|
centerSplitLeafs(splitAxis, splitValue, leafs, splitLeafs);
|
||||||
|
|
||||||
|
if (splitLeafs[0].empty() || splitLeafs[1].empty()) {
|
||||||
|
for (unsigned i = 0; i < 3 ; ++i) {
|
||||||
|
if (i == splitAxis)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
leafs.swap(splitLeafs[0]);
|
||||||
|
leafs.splice(leafs.begin(), splitLeafs[1]);
|
||||||
|
splitValue = box.getCenter()[i];
|
||||||
|
centerSplitLeafs(i, splitValue, leafs, splitLeafs);
|
||||||
|
|
||||||
|
if (!splitLeafs[0].empty() && !splitLeafs[1].empty()) {
|
||||||
|
splitAxis = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (splitLeafs[0].empty() || splitLeafs[1].empty()) {
|
||||||
|
leafs.swap(splitLeafs[0]);
|
||||||
|
leafs.splice(leafs.begin(), splitLeafs[1]);
|
||||||
|
equalSplitLeafs(splitAxis, leafs, splitLeafs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BVHStaticNode* child0 = buildTreeRecursive(splitLeafs[0]);
|
||||||
|
const BVHStaticNode* child1 = buildTreeRecursive(splitLeafs[1]);
|
||||||
|
if (!child0)
|
||||||
|
return child1;
|
||||||
|
if (!child1)
|
||||||
|
return child0;
|
||||||
|
|
||||||
|
return new BVHStaticBinary(splitAxis, child0, child1, box);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "BVHStaticLeaf.hxx"
|
||||||
|
#include "BVHVisitor.hxx"
|
||||||
|
|
||||||
|
namespace simgear {
|
||||||
|
|
||||||
|
BVHStaticLeaf::~BVHStaticLeaf()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user