Compare commits
434
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7f151ad02 | ||
|
|
0710b781d3 | ||
|
|
7c01ad6917 | ||
|
|
56d2f06631 | ||
|
|
9e47911b19 | ||
|
|
ef80497fbe | ||
|
|
e22cf106c2 | ||
|
|
5ffb270ec1 | ||
|
|
f85f3b0f25 | ||
|
|
e7ec83d626 | ||
|
|
11479cd8c3 | ||
|
|
176e760de1 | ||
|
|
430c60ed1a | ||
|
|
dfea3623f6 | ||
|
|
b38783e4cb | ||
|
|
9382a4c21b | ||
|
|
3cd4c5566f | ||
|
|
601c0977df | ||
|
|
c56f036bab | ||
|
|
44dd50c0ef | ||
|
|
56919ae45f | ||
|
|
6c14e7127d | ||
|
|
578af00b0d | ||
|
|
d6c0bf69b6 | ||
|
|
e8884b4ec0 | ||
|
|
5e79609955 | ||
|
|
4950c96f1c | ||
|
|
51b0cf535e | ||
|
|
4cc17a7f6e | ||
|
|
dca07c5634 | ||
|
|
fd42294faf | ||
|
|
c1246e8c4e | ||
|
|
59fc902cfb | ||
|
|
1fe9755d01 | ||
|
|
1da09a4706 | ||
|
|
f3c591469b | ||
|
|
b1200f9f59 | ||
|
|
47617d6c04 | ||
|
|
4794ab6095 | ||
|
|
bc85767f19 | ||
|
|
e37c218c2a | ||
|
|
a0aaa23904 | ||
|
|
27a6c72091 | ||
|
|
2dcc66f03e | ||
|
|
d70a05a088 | ||
|
|
c2317edf8a | ||
|
|
cb7ac404d9 | ||
|
|
5abc6c995f | ||
|
|
0f21c39e49 | ||
|
|
f6513127ce | ||
|
|
ddd72b2b37 | ||
|
|
7f5df1fb66 | ||
|
|
2e71b64de1 | ||
|
|
45f1f9263f | ||
|
|
878288f06a | ||
|
|
406cdf8d16 | ||
|
|
5b28b024ae | ||
|
|
7c693d8107 | ||
|
|
b8a6d1ac4d | ||
|
|
40533f50df | ||
|
|
539ced191b | ||
|
|
1a400b890b | ||
|
|
ebe5a5579c | ||
|
|
afb18ca75b | ||
|
|
01c62932bd | ||
|
|
6cd8db7b28 | ||
|
|
bb46d91bc6 | ||
|
|
3cd5322496 | ||
|
|
cadecdcab7 | ||
|
|
cd4030b7db | ||
|
|
0a2264cad4 | ||
|
|
bb2a02daa8 | ||
|
|
5991195062 | ||
|
|
54c4055af3 | ||
|
|
cb07210bc7 | ||
|
|
3e40d624a8 | ||
|
|
63ce675914 | ||
|
|
14e5e87a4d | ||
|
|
e7e81c6639 | ||
|
|
23d0601d82 | ||
|
|
6db9138eeb | ||
|
|
6a7c200002 | ||
|
|
e3f70b7125 | ||
|
|
a25e859fa7 | ||
|
|
5b2af1f6b3 | ||
|
|
59df72c4b0 | ||
|
|
4e2eb2f24c | ||
|
|
b905f4b8aa | ||
|
|
fefe87ed1e | ||
|
|
b66905c2f6 | ||
|
|
39472e4d81 | ||
|
|
85fba1325a | ||
|
|
0f39f05fa1 | ||
|
|
8d551c2664 | ||
|
|
346a22f684 | ||
|
|
b1571e4437 | ||
|
|
5ac2abe3ab | ||
|
|
5b15426cc6 | ||
|
|
1ac944b7c1 | ||
|
|
fd90dbb123 | ||
|
|
6ccad91537 | ||
|
|
c89db53ebf | ||
|
|
4ffd70a42a | ||
|
|
bbeb48a60d | ||
|
|
aefe9bc116 | ||
|
|
bcb95f647d | ||
|
|
145a7fa146 | ||
|
|
06f0b6030a | ||
|
|
191ee3a0ed | ||
|
|
f6358694ae | ||
|
|
af14d65a98 | ||
|
|
9fe75dc521 | ||
|
|
0051bea034 | ||
|
|
76c79dba8e | ||
|
|
84dc82506a | ||
|
|
ae1625734c | ||
|
|
e2ce4c0fa9 | ||
|
|
a06a15e769 | ||
|
|
7c5de29b61 | ||
|
|
5f9befebae | ||
|
|
6a7b885891 | ||
|
|
cd8e7bbdca | ||
|
|
5d731ad8c3 | ||
|
|
7964270929 | ||
|
|
ea513d392e | ||
|
|
feba9024eb | ||
|
|
b3e16ce8e0 | ||
|
|
31dd77c694 | ||
|
|
ae58f89fbf | ||
|
|
b3bc36b253 | ||
|
|
7287509fef | ||
|
|
b1c49045a8 | ||
|
|
0d5634475c | ||
|
|
e6bfe7d40c | ||
|
|
811cd0653f | ||
|
|
e2b8a21ff5 | ||
|
|
24c7941f65 | ||
|
|
600a9ee4c5 | ||
|
|
fdfdfedf01 | ||
|
|
a67688322d | ||
|
|
6fe057e277 | ||
|
|
f23e8bfb02 | ||
|
|
eab9da98f2 | ||
|
|
f161992836 | ||
|
|
40e13b91fe | ||
|
|
af6824605b | ||
|
|
babf58f8d2 | ||
|
|
968f5d7693 | ||
|
|
4cc6bd69ae | ||
|
|
199437e859 | ||
|
|
e5fac0a01d | ||
|
|
5d14b84969 | ||
|
|
bcccd06cee | ||
|
|
6b0ab9a49a | ||
|
|
023002ae73 | ||
|
|
579d384c04 | ||
|
|
e2e1524454 | ||
|
|
4a5853c1c2 | ||
|
|
64756d14d0 | ||
|
|
bac2ef601d | ||
|
|
cf3bab89f9 | ||
|
|
dfe41ad984 | ||
|
|
b784bebaa9 | ||
|
|
bcf727cf58 | ||
|
|
ecd0a53412 | ||
|
|
3456434e37 | ||
|
|
454c5b1ed2 | ||
|
|
dc2c437a1a | ||
|
|
819d3f5ded | ||
|
|
4f802689f2 | ||
|
|
9cbbe55598 | ||
|
|
7e2dafdcb8 | ||
|
|
c7873d68f7 | ||
|
|
939ec526a8 | ||
|
|
b20a635db0 | ||
|
|
a656bee0df | ||
|
|
42f07e3f14 | ||
|
|
5803b05bd5 | ||
|
|
ccf0ba50c4 | ||
|
|
f3bc977d32 | ||
|
|
80609e0816 | ||
|
|
795d481ca6 | ||
|
|
1b936b9af8 | ||
|
|
f141cc28b0 | ||
|
|
4cb64b58be | ||
|
|
028af34d3d | ||
|
|
ce54997be5 | ||
|
|
3d213fa713 | ||
|
|
e71f3790ce | ||
|
|
67b9cba4d3 | ||
|
|
78a471f684 | ||
|
|
d4289c5d54 | ||
|
|
0c17c5440a | ||
|
|
c4116da564 | ||
|
|
d0821953bb | ||
|
|
e782adef94 | ||
|
|
d3572c2562 | ||
|
|
1f3838b155 | ||
|
|
6aa459073e | ||
|
|
0932c33185 | ||
|
|
5e542aa841 | ||
|
|
6d53abd5af | ||
|
|
3ea58bf8db | ||
|
|
71a4c2c3d2 | ||
|
|
a3e391a523 | ||
|
|
9cb15b302c | ||
|
|
15c1a28d37 | ||
|
|
d3a500e54e | ||
|
|
a0a5eb8aef | ||
|
|
a92955eade | ||
|
|
f043f3d4f9 | ||
|
|
992a057a1b | ||
|
|
07da1e7e1a | ||
|
|
2c07222ef6 | ||
|
|
918e315d47 | ||
|
|
c824731bc6 | ||
|
|
0c39caa622 | ||
|
|
1f1e28baf8 | ||
|
|
0c303389d6 | ||
|
|
01a896ef5b | ||
|
|
0e5e760135 | ||
|
|
7e7d877874 | ||
|
|
57ccb6fd6b | ||
|
|
efa2876e29 | ||
|
|
59ef7d8fd1 | ||
|
|
1f308c9ec3 | ||
|
|
4943d3aa53 | ||
|
|
828d561113 | ||
|
|
fcf72a7123 | ||
|
|
d3f5bc6e2d | ||
|
|
f525a05be8 | ||
|
|
fc7ec4299e | ||
|
|
21d053b1b6 | ||
|
|
68e64a5aa7 | ||
|
|
8e718fe288 | ||
|
|
efec9070e1 | ||
|
|
e3646d4d4a | ||
|
|
4219f16f61 | ||
|
|
c3b1802e95 | ||
|
|
40fe078021 | ||
|
|
a5a6600e74 | ||
|
|
03b9303f22 | ||
|
|
b5a59ea6f9 | ||
|
|
c6b2124129 | ||
|
|
d320a6facb | ||
|
|
0793c2cb8c | ||
|
|
d14755abb8 | ||
|
|
abd4aa2e6b | ||
|
|
58417e78e5 | ||
|
|
390eb1c6e9 | ||
|
|
d4c6530a72 | ||
|
|
ff17b44a41 | ||
|
|
5bd2d47571 | ||
|
|
f8e475cd34 | ||
|
|
a05e063949 | ||
|
|
eb06a90109 | ||
|
|
e2f6632fee | ||
|
|
5c5c583dcc | ||
|
|
0d8d5c02d0 | ||
|
|
382e0c6ad2 | ||
|
|
a8d1c44408 | ||
|
|
78b4318c34 | ||
|
|
b47031a099 | ||
|
|
0f7b65a921 | ||
|
|
33f7903aeb | ||
|
|
f3c2740917 | ||
|
|
09a57c7a52 | ||
|
|
9068f0606e | ||
|
|
c577b7e369 | ||
|
|
5850464ba7 | ||
|
|
50e240d5e4 | ||
|
|
75c2a45b25 | ||
|
|
c958d63897 | ||
|
|
b633b8d0d3 | ||
|
|
76948416a9 | ||
|
|
f4a527c57c | ||
|
|
c491baff0e | ||
|
|
6d05fc6f57 | ||
|
|
ca53add820 | ||
|
|
6fe3099ab4 | ||
|
|
a34eceb327 | ||
|
|
c9042c3186 | ||
|
|
b46fe0d51c | ||
|
|
6d1d3173fe | ||
|
|
030d044d03 | ||
|
|
29fb8e0f74 | ||
|
|
6e326976d5 | ||
|
|
03a7d72a62 | ||
|
|
f913febd71 | ||
|
|
daa0fbdc6b | ||
|
|
d4c52b599d | ||
|
|
ec88373eb7 | ||
|
|
4286cafdeb | ||
|
|
3880d8e2f2 | ||
|
|
671c84ad44 | ||
|
|
a0d687bb24 | ||
|
|
704385ff0a | ||
|
|
81a657edec | ||
|
|
9d0bad29c0 | ||
|
|
2fb8e32104 | ||
|
|
c522e499b2 | ||
|
|
4700955480 | ||
|
|
2c66081fa4 | ||
|
|
855e88da43 | ||
|
|
ad302db9a8 | ||
|
|
bfa5fff500 | ||
|
|
01c64fd554 | ||
|
|
13a2b92a32 | ||
|
|
29e79f8f61 | ||
|
|
8f7527ede0 | ||
|
|
7cd149a4d8 | ||
|
|
e45912fd8a | ||
|
|
56c4ba67c6 | ||
|
|
7e7ce2f38e | ||
|
|
7dc9eba2d0 | ||
|
|
f91d96b51a | ||
|
|
bc19609147 | ||
|
|
1ccaf3a0bd | ||
|
|
03bfd829da | ||
|
|
e1f7a1e0a0 | ||
|
|
ceeac0ecf0 | ||
|
|
c9d0eac739 | ||
|
|
8f24d924ee | ||
|
|
8537cc9edf | ||
|
|
58f3985567 | ||
|
|
872db67f21 | ||
|
|
006f90997a | ||
|
|
26b4776394 | ||
|
|
66c64459e6 | ||
|
|
dc8657f57f | ||
|
|
9d647b90e0 | ||
|
|
f5730c950b | ||
|
|
15d37daebd | ||
|
|
795c9876af | ||
|
|
45f653167d | ||
|
|
403d9b6ac1 | ||
|
|
722af5f659 | ||
|
|
471b9f02ec | ||
|
|
fd294b6f98 | ||
|
|
88baaa72be | ||
|
|
61084cf1ba | ||
|
|
5b63f0755a | ||
|
|
9eb5cf6c98 | ||
|
|
679db5a22b | ||
|
|
0e35168bdb | ||
|
|
035dcc7ab7 | ||
|
|
252deed5b9 | ||
|
|
c2c4cad753 | ||
|
|
42e76477cf | ||
|
|
1eade74e5a | ||
|
|
f1f0fa0aa9 | ||
|
|
deef158822 | ||
|
|
fef2006663 | ||
|
|
5c97fd576a | ||
|
|
c4eb6b7b65 | ||
|
|
31324761cc | ||
|
|
e495f03ee9 | ||
|
|
f5769627e4 | ||
|
|
06ad73f85b | ||
|
|
fa20363853 | ||
|
|
2564432e71 | ||
|
|
addf47600d | ||
|
|
7f534a7966 | ||
|
|
eabffece1f | ||
|
|
afed842ad1 | ||
|
|
c46cfb5d47 | ||
|
|
34fe42bbd9 | ||
|
|
0c1d96b749 | ||
|
|
9b67f52d56 | ||
|
|
d37907d35d | ||
|
|
fee8d0cf78 | ||
|
|
f5f9c6b81f | ||
|
|
4e3460a34b | ||
|
|
8545b6ce6b | ||
|
|
e417903c23 | ||
|
|
81eae3fa48 | ||
|
|
90c58087e8 | ||
|
|
19bc1e6313 | ||
|
|
4a4e8c87b8 | ||
|
|
f04e559dc2 | ||
|
|
8e5e657344 | ||
|
|
a4f1f62068 | ||
|
|
a3e279f06f | ||
|
|
d11954e80c | ||
|
|
812170ebce | ||
|
|
fdd3c77298 | ||
|
|
342de209a2 | ||
|
|
caeb32488e | ||
|
|
ff7e70f4d5 | ||
|
|
950f51909c | ||
|
|
f86e6d344c | ||
|
|
08581282dd | ||
|
|
e1e47e76ec | ||
|
|
3ff059848c | ||
|
|
22c7df5936 | ||
|
|
81a44d1340 | ||
|
|
2c089e6166 | ||
|
|
589dae7b0c | ||
|
|
3ff13189aa | ||
|
|
7151c3fac1 | ||
|
|
3e023b77dd | ||
|
|
e3fc89890c | ||
|
|
ce2a6cfe5c | ||
|
|
31d9eaf54c | ||
|
|
781c445d14 | ||
|
|
26a416399f | ||
|
|
f7dc7f039e | ||
|
|
3c74fea087 | ||
|
|
be0635bfd3 | ||
|
|
6723ef95c2 | ||
|
|
1a8fd62680 | ||
|
|
8b57ed46b1 | ||
|
|
25c08e56c2 | ||
|
|
0f148b6ab6 | ||
|
|
47575fe357 | ||
|
|
7c14453b5a | ||
|
|
a47d5536fa | ||
|
|
db8f7f21e8 | ||
|
|
3c312c55f1 | ||
|
|
2d11419cba | ||
|
|
07a4508944 | ||
|
|
62913739bb | ||
|
|
55e9d8d944 | ||
|
|
a9439d58c7 | ||
|
|
800ad40c4c | ||
|
|
62864637a3 | ||
|
|
4d4ac7ea24 | ||
|
|
119651482d | ||
|
|
ecf0a1a736 | ||
|
|
94942d1ac4 | ||
|
|
b0a5b54949 | ||
|
|
ac57eab8ac | ||
|
|
74a4144193 | ||
|
|
5c44cb0f01 |
-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>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
+1
-1
@@ -671,7 +671,7 @@ if test "x$want_boost" = "xyes"; 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_NOTICE([Your boost libraries seems to old (version $_version).])
|
||||
AC_MSG_ERROR([Your boost libraries seems to old (version $_version).])
|
||||
fi
|
||||
else
|
||||
AC_SUBST(BOOST_CPPFLAGS)
|
||||
|
||||
+119
-6
@@ -8,7 +8,7 @@ dnl Require at least automake 2.52
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
dnl Initialize the automake stuff
|
||||
AM_INIT_AUTOMAKE(SimGear, 1.9.0)
|
||||
AM_INIT_AUTOMAKE(SimGear, 2.0.0-rc2)
|
||||
|
||||
dnl Specify KAI C++ compiler and flags.
|
||||
dnl Borrowed with slight modification from blitz distribution.
|
||||
@@ -37,7 +37,7 @@ AC_PROG_CXX
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AX_BOOST_BASE([1.34.0])
|
||||
AX_BOOST_BASE([1.37.0])
|
||||
|
||||
if test "x$BOOST_CPPFLAGS" != "x-I/usr/include" ; then
|
||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
||||
@@ -126,6 +126,12 @@ if test "x$with_plib" != "x" ; then
|
||||
EXTRA_DIRS="${EXTRA_DIRS} $with_plib"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(plib_framework, [ --with-plib-framework=PREFIX Specify the prefix path to PLIB.framework ])
|
||||
|
||||
if test "x$with_plib_framework" != "x"; then
|
||||
echo "plib framework prefix is $with_plib_framework"
|
||||
fi
|
||||
|
||||
# specify the osg location
|
||||
AC_ARG_WITH(osg, [ --with-osg=PREFIX Specify the prefix path to osg])
|
||||
|
||||
@@ -134,6 +140,21 @@ if test "x$with_osg" != "x" ; then
|
||||
EXTRA_DIRS="${EXTRA_DIRS} $with_osg"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(osg_framework, [ --with-osg-framework=PREFIX Specify the prefix path to OSG.framework ])
|
||||
|
||||
if test "x$with_osg_framework" != "x"; then
|
||||
echo "osg framework prefix is $with_osg_framework"
|
||||
CPPFLAGS = "$CPPFLAGS -F$with-osg-framework"
|
||||
export DYLD_FRAMEWORK_PATH="$DYLD_FRAMEWORK_PATH:$with_osg_framework"
|
||||
fi
|
||||
|
||||
dnl specifying OpenAL.framework (for user provided OpenAL.framework / ALUT)
|
||||
AC_ARG_WITH(openal_framework, [ --with-openal-framework=PREFIX Speicfy the prefix path to OpenAL.framework ])
|
||||
|
||||
if test "x$with_openal_framework" != "x"; then
|
||||
echo "OpenAL framework prefix is $with_openal_framework"
|
||||
fi
|
||||
|
||||
dnl Determine an extra directories to add to include/lib search paths
|
||||
case "${host}" in
|
||||
*-apple-darwin* | *-*-cygwin* | *-*-mingw32*)
|
||||
@@ -203,6 +224,7 @@ LIBS=""
|
||||
|
||||
dnl check for some default libraries
|
||||
AC_SEARCH_LIBS(cos, m)
|
||||
AC_SEARCH_LIBS(clock_gettime, rt)
|
||||
|
||||
base_LIBS="$LIBS"
|
||||
|
||||
@@ -292,9 +314,54 @@ case "${host}" in
|
||||
|
||||
LIBS="$LIBS -framework IOKit -framework OpenAL"
|
||||
openal_LIBS="$LIBS"
|
||||
# not sure how to test if OpenAL exists on MacOS (does it come by default?)
|
||||
OPENAL_OK="yes"
|
||||
ALUT_OK="yes"
|
||||
ALUT_OK="no"
|
||||
|
||||
if test "x$with_openal_lib" != "x"; then
|
||||
echo "libopenal is not supported on Mac OS platform."
|
||||
openal_LIBS=""
|
||||
fi
|
||||
OPENAL_OK="yes"
|
||||
# Looking for alut.h, if found assume that it is a part of
|
||||
# the OpenAL package.
|
||||
AC_CHECK_HEADERS([OpenAL/alut.h],[ALUT_OK="yes"])
|
||||
|
||||
|
||||
dnl Thank you Christian Bauer from SheepSaver
|
||||
dnl Modified by Tatsuhiro Nishioka for accepting a given framework path
|
||||
dnl AC_CHECK_FRAMEWORK($1=NAME, $2=INCLUDES, $3=FRAMEWORK_PATH) ; $3 is optional
|
||||
AC_DEFUN([AC_CHECK_FRAMEWORK], [
|
||||
AS_VAR_PUSHDEF([ac_Framework], [ac_cv_framework_$1])dnl
|
||||
AC_CACHE_CHECK([whether compiler supports framework $1],
|
||||
ac_Framework, [
|
||||
saved_LIBS="$LIBS"
|
||||
FRAMEWORKS="$FRAMEWORKS -framework $1"
|
||||
if test "$3" = ""; then
|
||||
FRAMEWORKS="$FRAMEWORKS $ADD2LD"
|
||||
elif test "`echo $FRAMEWORKS | grep -- -F$3`" = ""; then
|
||||
FRAMEWORKS="$FRAMEWORKS -F$3"
|
||||
CXXFLAGS="$CXXFLAGS -F$3"
|
||||
CCFLAGS="$CCFLAGS -F$3"
|
||||
dnl This is needed for AC_TRY_LINK when a framework path is specified
|
||||
export DYLD_FRAMEWORK_PATH="${DYLD_FRAMEWORK_PATH}:$3"
|
||||
fi
|
||||
AC_TRY_LINK(
|
||||
[$2], [],
|
||||
[AS_VAR_SET(ac_Framework, yes)], [AS_VAR_SET(ac_Framework, no); LIBS="$saved_LIBS"]
|
||||
)
|
||||
])
|
||||
AS_IF([test AS_VAR_GET(ac_Framework) = yes],
|
||||
[AC_DEFINE(AS_TR_CPP(HAVE_FRAMEWORK_$1), 1, [Define if framework $1 is available.])]
|
||||
)
|
||||
AS_VAR_POPDEF([ac_Framework])dnl
|
||||
])
|
||||
|
||||
dnl Check for OpenAL.framework when --with-openal-framework is specified
|
||||
dnl Of cource OpenAL.framework needs to have alut.h
|
||||
if test "x$with_openal_framework" != "x"; then
|
||||
AC_CHECK_FRAMEWORK(OpenAL, [#include <OpenAL/alut.h>], $with_openal_framework)
|
||||
fi
|
||||
|
||||
;;
|
||||
|
||||
*)
|
||||
@@ -351,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++
|
||||
# compiler
|
||||
|
||||
CXXCPP="g++ -E"
|
||||
AC_LANG_PUSH(C++)
|
||||
|
||||
dnl Check for "plib" without which we cannot go on
|
||||
case ${host} in
|
||||
*-apple-darwin*)
|
||||
# Check PLIB framework availability when with-plib-framework is specified
|
||||
if test "x$with_plib_framework" != "x"; then
|
||||
AC_CHECK_FRAMEWORK(PLIB, [#include <plib/ul.h>], $with_plib_framework)
|
||||
plib_FRAMEWORK="$FRAMEWORKS"
|
||||
FRAMEWORKS=""
|
||||
AC_SUBST(plib_FRAMEWORK)
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AM_CONDITIONAL(HAVE_FRAMEWORK_PLIB, test "x$ac_cv_framework_PLIB" != "x")
|
||||
|
||||
AC_CHECK_HEADER(plib/ul.h)
|
||||
if test "x$ac_cv_header_plib_ul_h" != "xyes"; then
|
||||
echo
|
||||
@@ -373,8 +454,6 @@ AC_TRY_RUN([
|
||||
#define MIN_PLIB_VERSION 185
|
||||
|
||||
int main() {
|
||||
int major, minor, micro;
|
||||
|
||||
if ( PLIB_VERSION < MIN_PLIB_VERSION ) {
|
||||
return -1;
|
||||
}
|
||||
@@ -391,8 +470,40 @@ int main() {
|
||||
|
||||
LIBS="$saved_LIBS"
|
||||
|
||||
# OpenSceneGraph
|
||||
case "${host}" in
|
||||
*-apple-darwin*)
|
||||
if test "x$with_osg_framework" != "x"; then
|
||||
AC_CHECK_FRAMEWORK(osgViewer, [#include <osgViewer/Version>], $with_osg_framework)
|
||||
AC_CHECK_FRAMEWORK(osgGA, [#include <osgGA/Version>], $with_osg_framework)
|
||||
AC_CHECK_FRAMEWORK(osgText, [#include <osgText/Version>], $with_osg_framework)
|
||||
AC_CHECK_FRAMEWORK(osgFX, [#include <osgFX/AnisotropicLighting>], $with_osg_framework)
|
||||
AC_CHECK_FRAMEWORK(osgUtil, [#include <osgUtil/Version>], $with_osg_framework)
|
||||
AC_CHECK_FRAMEWORK(osgDB, [#include <osgDB/Version>], $with_osg_framework)
|
||||
AC_CHECK_FRAMEWORK(osgSim, [#include <osgSim/Version>], $with_osg_framework)
|
||||
AC_CHECK_FRAMEWORK(osgParticle, [#include <osgParticle/Version>], $with_osg_framework)
|
||||
AC_CHECK_FRAMEWORK(osg, [#include <osg/Version>], $with_osg_framework)
|
||||
osg_FRAMEWORKS="$FRAMEWORKS"
|
||||
FRAMEWORKS=""
|
||||
AC_SUBST(osg_FRAMEWORKS)
|
||||
AC_CHECK_FRAMEWORK(OpenThreads, [#include <OpenThreads/Version>], $with_osg_framework)
|
||||
openthreads_FRAMEWORK="$FRAMEWORKS"
|
||||
FRAMEWORKS=""
|
||||
AC_SUBST(openthreads_FRAMEWORK)
|
||||
else
|
||||
dnl
|
||||
dnl This is needed when osg dynamic libs are specified
|
||||
dnl instead of OSG frameworks on Mac OS X
|
||||
dnl
|
||||
LDFLAGS="$LDFLAGS -L$with_osg"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AM_CONDITIONAL(HAVE_FRAMEWORK_OSG, test "x$ac_cv_framework_osg" != "x")
|
||||
|
||||
AC_CHECK_HEADER(osg/Version)
|
||||
if test "x$ac_cv_header_osg_Version" != "xyes"; then
|
||||
if test "x$ac_cv_framework_osg" != "xyes"; then
|
||||
echo
|
||||
echo "You *must* have the OpenSceneGraph support library installed on your system"
|
||||
echo "to build this version of SimGear!"
|
||||
@@ -401,6 +512,7 @@ if test "x$ac_cv_header_osg_Version" != "xyes"; then
|
||||
echo
|
||||
echo "configure aborted."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADER(boost/version.hpp)
|
||||
@@ -480,6 +592,7 @@ AC_CONFIG_FILES([ \
|
||||
simgear/props/Makefile \
|
||||
simgear/route/Makefile \
|
||||
simgear/scene/Makefile \
|
||||
simgear/scene/bvh/Makefile \
|
||||
simgear/scene/material/Makefile \
|
||||
simgear/scene/model/Makefile \
|
||||
simgear/scene/sky/Makefile \
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Debug
|
||||
Release
|
||||
SimGear.ncb
|
||||
SimGear.suo
|
||||
SimGear.suo
|
||||
*.user
|
||||
|
||||
+194
-29
@@ -23,7 +23,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..;..\..\simgear;..\..\..;..\..\..\install\msvc71\OpenSceneGraph\include;..\..\..\3rdparty\include;"..\..\..\pthreads-w32-2-7-0-release";..\..\..\boost_1_36_0"
|
||||
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"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="2"
|
||||
@@ -75,7 +75,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..;..\..\simgear;..\..\..;..\..\..\install\msvc71\OpenSceneGraph\include;..\..\..\3rdparty\include;"..\..\..\pthreads-w32-2-7-0-release";..\..\..\boost_1_36_0"
|
||||
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"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
@@ -287,6 +287,9 @@
|
||||
<Filter
|
||||
Name="Lib_sgmath"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\..\simgear\math\beziercurve.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\math\interpolater.cxx">
|
||||
</File>
|
||||
@@ -422,9 +425,6 @@
|
||||
<File
|
||||
RelativePath="..\..\simgear\screen\colors.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\screen\colours.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\screen\extensions.cxx">
|
||||
</File>
|
||||
@@ -461,12 +461,6 @@
|
||||
<File
|
||||
RelativePath="..\..\simgear\screen\shader.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\screen\texture.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\screen\texture.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\screen\tr.cxx">
|
||||
</File>
|
||||
@@ -649,6 +643,15 @@
|
||||
<Filter
|
||||
Name="Lib_sgprops"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\AtomicChangeListener.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\AtomicChangeListener.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\ExtendedPropertyAdapter.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\props\condition.cxx">
|
||||
</File>
|
||||
@@ -683,12 +686,6 @@
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\CheckSceneryVisitor.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\location.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\location.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\model.cxx">
|
||||
</File>
|
||||
@@ -725,18 +722,18 @@
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\placement.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\placementtrans.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\placementtrans.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\SGClipGroup.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\SGClipGroup.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\SGInteractionAnimation.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\SGInteractionAnimation.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\model\SGMaterialAnimation.cxx">
|
||||
</File>
|
||||
@@ -811,6 +808,53 @@
|
||||
<Filter
|
||||
Name="Lib_sgmaterial"
|
||||
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
|
||||
RelativePath="..\..\simgear\scene\material\mat.cxx">
|
||||
</File>
|
||||
@@ -829,6 +873,18 @@
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\material\matmodel.hxx">
|
||||
</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
|
||||
Name="Lib_sgtgdb"
|
||||
@@ -924,12 +980,6 @@
|
||||
<File
|
||||
RelativePath="..\..\simgear\threads\SGQueue.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\threads\SGThread.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\threads\SGThread.hxx">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Lib_sgstructure"
|
||||
@@ -1130,12 +1180,24 @@
|
||||
<Filter
|
||||
Name="Lib_sgutil"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\CopyOp.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\CopyOp.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\NodeAndDrawableVisitor.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\NodeAndDrawableVisitor.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\PrimitiveUtils.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\PrimitiveUtils.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\QuadTreeBuilder.cxx">
|
||||
</File>
|
||||
@@ -1184,12 +1246,115 @@
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\SGUpdateVisitor.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\SplicingVisitor.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\SplicingVisitor.hxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.cxx">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simgear\scene\util\StateAttributeFactory.hxx">
|
||||
</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>
|
||||
<File
|
||||
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
+2008
-1420
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 ) {
|
||||
x = (int)((dlon - lon) / span);
|
||||
} else {
|
||||
if ( (dlon >= 0) || (fabs(diff) < SG_EPSILON) ) {
|
||||
if ( dlon >= 0 ) {
|
||||
lon = (int)( (int)(lon / span) * span);
|
||||
} else {
|
||||
// cout << " lon = " << lon
|
||||
|
||||
@@ -95,7 +95,6 @@ static double sg_bucket_span( double l ) {
|
||||
class SGBucket {
|
||||
|
||||
private:
|
||||
double cx, cy; // centerpoint (lon, lat) in degrees of bucket
|
||||
short lon; // longitude index (-180 to 179)
|
||||
short lat; // latitude index (-90 to 89)
|
||||
char x; // x subdivision (0 to 7)
|
||||
|
||||
+27
-1
@@ -131,9 +131,35 @@
|
||||
//
|
||||
|
||||
#ifdef __APPLE__
|
||||
# ifdef __GNUC__
|
||||
# if ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 3 )
|
||||
inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
|
||||
#else
|
||||
# else
|
||||
// any C++ header file undefines isinf and isnan
|
||||
// so this should be included before <iostream>
|
||||
// the functions are STILL in libm (libSystem on mac os x)
|
||||
extern "C" int (isnan)(double);
|
||||
extern "C" int (isinf)(double);
|
||||
# endif
|
||||
# else
|
||||
inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__FreeBSD__)
|
||||
# if __FreeBSD_version < 500000
|
||||
extern "C" {
|
||||
inline int isnan(double r) { return !(r <= 0 || r >= 0); }
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__CYGWIN__)
|
||||
# include <ieeefp.h> // isnan
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
# define isnan(x) _isnan(x)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+5
-5
@@ -118,10 +118,10 @@
|
||||
/** Nautical Miles to Radians */
|
||||
#define SG_RAD_TO_NM 3437.7467707849392526
|
||||
|
||||
/** Miles per second to Knots */
|
||||
/** meters per second to Knots */
|
||||
#define SG_MPS_TO_KT 1.9438444924406046432
|
||||
|
||||
/** Knots to Miles per second */
|
||||
/** Knots to meters per second */
|
||||
#define SG_KT_TO_MPS 0.5144444444444444444
|
||||
|
||||
/** Feet per second to Knots */
|
||||
@@ -130,16 +130,16 @@
|
||||
/** Knots to Feet per second */
|
||||
#define SG_KT_TO_FPS 1.6878098571011956874
|
||||
|
||||
/** Miles per second to Miles per hour */
|
||||
/** meters per second to Miles per hour */
|
||||
#define SG_MPS_TO_MPH 2.2369362920544020312
|
||||
|
||||
/** Miles per hour to Miles per second */
|
||||
/** meetrs per hour to Miles per second */
|
||||
#define SG_MPH_TO_MPS 0.44704
|
||||
|
||||
/** Meters per second to Kilometers per hour */
|
||||
#define SG_MPS_TO_KMH 3.6
|
||||
|
||||
/** Kilometers per hour to Miles per second */
|
||||
/** Kilometers per hour to meters per second */
|
||||
#define SG_KMH_TO_MPS 0.2777777777777777778
|
||||
|
||||
/** Pascal to Inch Mercury */
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <streambuf>
|
||||
#include <ostream>
|
||||
#include <cstdio>
|
||||
|
||||
#include <simgear/debug/debug_types.h>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <string>
|
||||
#include "Debug/logstream.hxx"
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
class Test {
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/math/polar3d.hxx>
|
||||
#include <simgear/sound/soundmgr_openal.hxx>
|
||||
#include <simgear/sound/sample_group.hxx>
|
||||
#include <simgear/scene/sky/cloudfield.hxx>
|
||||
#include <simgear/scene/sky/newcloud.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
@@ -175,7 +175,7 @@ SGEnviro::SGEnviro() :
|
||||
lightning_enable_state(false),
|
||||
elapsed_time(0.0),
|
||||
dt(0.0),
|
||||
soundMgr(NULL),
|
||||
sampleGroup(NULL),
|
||||
snd_active(false),
|
||||
snd_dist(0.0),
|
||||
min_time_before_lt(0.0),
|
||||
@@ -189,6 +189,8 @@ SGEnviro::SGEnviro() :
|
||||
}
|
||||
|
||||
SGEnviro::~SGEnviro(void) {
|
||||
if (sampleGroup) delete sampleGroup;
|
||||
|
||||
// OSGFIXME
|
||||
return;
|
||||
list_of_lightning::iterator iLightning;
|
||||
@@ -530,8 +532,8 @@ void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed
|
||||
|
||||
}
|
||||
|
||||
void SGEnviro::set_soundMgr(SGSoundMgr *mgr) {
|
||||
soundMgr = mgr;
|
||||
void SGEnviro::set_sampleGroup(SGSampleGroup *sgr) {
|
||||
sampleGroup = sgr;
|
||||
}
|
||||
|
||||
void SGEnviro::drawPrecipitation(double rain_norm, double snow_norm, double hail_norm, double pitch, double roll, double heading, double hspeed) {
|
||||
@@ -616,7 +618,7 @@ void SGLightning::lt_build(void) {
|
||||
top[PY] = alt;
|
||||
top[PZ] = 0;
|
||||
lt_build_tree_branch(0, top, 1.0, 50, top[PY] / 8.0);
|
||||
if( ! sgEnviro.soundMgr )
|
||||
if( ! sgEnviro.sampleGroup )
|
||||
return;
|
||||
Point3D start( sgEnviro.last_lon*SG_DEGREES_TO_RADIANS, sgEnviro.last_lat*SG_DEGREES_TO_RADIANS, 0.0 );
|
||||
Point3D dest( lon*SG_DEGREES_TO_RADIANS, lat*SG_DEGREES_TO_RADIANS, 0.0 );
|
||||
@@ -737,7 +739,7 @@ void SGEnviro::drawLightning(void) {
|
||||
return;
|
||||
list_of_lightning::iterator iLightning;
|
||||
// play 'thunder' for lightning
|
||||
if( snd_active )
|
||||
if( snd_active ) {
|
||||
if( !snd_playing ) {
|
||||
// wait until sound has reached us
|
||||
snd_timer += dt;
|
||||
@@ -751,20 +753,21 @@ void SGEnviro::drawLightning(void) {
|
||||
double ax = 0.0, ay = 0.0;
|
||||
ax = cos(course) * dist;
|
||||
ay = sin(course) * dist;
|
||||
SGSharedPtr<SGSoundSample> snd = soundMgr->find("thunder");
|
||||
SGSharedPtr<SGSoundSample> snd = sampleGroup->find("thunder");
|
||||
if( snd ) {
|
||||
ALfloat pos[3]={ax, ay, -sgEnviro.last_alt };
|
||||
snd->set_source_pos(pos);
|
||||
SGVec3d pos = SGVec3d(ax, ay, -sgEnviro.last_alt);
|
||||
snd->set_position(pos);
|
||||
snd->play_once();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if( !soundMgr->is_playing("thunder") ) {
|
||||
if( !sampleGroup->is_playing("thunder") ) {
|
||||
snd_active = false;
|
||||
snd_playing = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if( ! lightning_enable_state )
|
||||
return;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ using std::vector;
|
||||
using std::string;
|
||||
|
||||
class SGLightning;
|
||||
class SGSoundMgr;
|
||||
class SGSampleGroup;
|
||||
|
||||
/**
|
||||
* Simulate some echo on a weather radar.
|
||||
@@ -84,7 +84,7 @@ private:
|
||||
sgVec4 fog_color;
|
||||
sgMat4 transform;
|
||||
double last_lon, last_lat, last_alt;
|
||||
SGSoundMgr *soundMgr;
|
||||
SGSampleGroup *sampleGroup;
|
||||
bool snd_active, snd_playing;
|
||||
double snd_timer, snd_wait, snd_pos_lat, snd_pos_lon, snd_dist;
|
||||
double min_time_before_lt;
|
||||
@@ -243,7 +243,7 @@ public:
|
||||
* Forward the sound manager instance to be able to play samples.
|
||||
* @param mgr a running sound manager
|
||||
*/
|
||||
void set_soundMgr(SGSoundMgr *mgr);
|
||||
void set_sampleGroup(SGSampleGroup *sgr);
|
||||
|
||||
void setFOV( float w, float h );
|
||||
void getFOV( float &w, float &h );
|
||||
|
||||
@@ -158,6 +158,7 @@ public:
|
||||
* @return planets array
|
||||
*/
|
||||
inline SGVec3d *getPlanets() { return planets; }
|
||||
inline const SGVec3d *getPlanets() const { return planets; }
|
||||
|
||||
/** @return the numbers of defined stars. */
|
||||
inline int getNumStars() const { return stars->getNumStars(); }
|
||||
@@ -170,6 +171,7 @@ public:
|
||||
* @returns star array
|
||||
*/
|
||||
inline SGVec3d *getStars() { return stars->getStars(); }
|
||||
inline const SGVec3d *getStars() const { return stars->getStars(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
+22
-4
@@ -26,36 +26,54 @@ noinst_PROGRAMS = decode_binobj socktest lowtest tcp_server tcp_client
|
||||
|
||||
tcp_server_SOURCES = tcp_server.cxx
|
||||
|
||||
if HAVE_FRAMEWORK_PLIB
|
||||
tcp_server_LDFLAGS = $(plib_FRAMEWORK)
|
||||
else
|
||||
tcp_server_PLIB_LIBS = -lplibnet -lplibul
|
||||
endif
|
||||
|
||||
tcp_server_LDADD = \
|
||||
libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||
-lplibnet -lplibul -lz \
|
||||
$(tcp_server_PLIB_LIBS) -lz \
|
||||
$(network_LIBS) \
|
||||
$(base_LIBS)
|
||||
|
||||
tcp_client_SOURCES = tcp_client.cxx
|
||||
|
||||
if HAVE_FRAMEWORK_PLIB
|
||||
tcp_client_LDFLAGS = $(plib_FRAMEWORK)
|
||||
else
|
||||
tcp_client_PLIB_LIBS = -lplibnet -lplibul
|
||||
endif
|
||||
|
||||
tcp_client_LDADD = \
|
||||
libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||
-lplibnet -lplibul -lz \
|
||||
$(tcp_client_PLIB_LIBS) -lz \
|
||||
$(network_LIBS) \
|
||||
$(base_LIBS)
|
||||
|
||||
socktest_SOURCES = socktest.cxx
|
||||
|
||||
if HAVE_FRAMEWORK_PLIB
|
||||
socktest_LDFLAGS = $(plib_FRAMEWORK)
|
||||
else
|
||||
socktest_PLIB_LIBS = -lplibnet -lplibul
|
||||
endif
|
||||
|
||||
socktest_LDADD = \
|
||||
libsgio.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/bucket/libsgbucket.a \
|
||||
$(top_builddir)/simgear/misc/libsgmisc.a \
|
||||
-lplibnet -lplibul -lz \
|
||||
$(socktest_PLIB_LIBS) -lz
|
||||
$(network_LIBS) \
|
||||
$(base_LIBS)
|
||||
$(base_LIBS)
|
||||
|
||||
lowtest_SOURCES = lowtest.cxx
|
||||
|
||||
|
||||
+16
-8
@@ -55,21 +55,25 @@ void sgWriteChar ( gzFile fd, const char var )
|
||||
|
||||
void sgReadFloat ( gzFile fd, float *var )
|
||||
{
|
||||
if ( gzread ( fd, var, sizeof(float) ) != sizeof(float) ) {
|
||||
union { float v; uint32_t u; } buf;
|
||||
if ( gzread ( fd, &buf.u, sizeof(float) ) != sizeof(float) ) {
|
||||
read_error = true ;
|
||||
}
|
||||
if ( sgIsBigEndian() ) {
|
||||
sgEndianSwap( (uint32_t *)var);
|
||||
sgEndianSwap( &buf.u );
|
||||
}
|
||||
*var = buf.v;
|
||||
}
|
||||
|
||||
|
||||
void sgWriteFloat ( gzFile fd, const float var )
|
||||
{
|
||||
union { float v; uint32_t u; } buf;
|
||||
buf.v = var;
|
||||
if ( sgIsBigEndian() ) {
|
||||
sgEndianSwap( (uint32_t *)&var);
|
||||
sgEndianSwap( &buf.u );
|
||||
}
|
||||
if ( gzwrite ( fd, (void *)(&var), sizeof(float) ) != sizeof(float) ) {
|
||||
if ( gzwrite ( fd, (void *)(&buf.u), sizeof(float) ) != sizeof(float) ) {
|
||||
write_error = true ;
|
||||
}
|
||||
}
|
||||
@@ -77,21 +81,25 @@ void sgWriteFloat ( gzFile fd, const float var )
|
||||
|
||||
void sgReadDouble ( gzFile fd, double *var )
|
||||
{
|
||||
if ( gzread ( fd, var, sizeof(double) ) != sizeof(double) ) {
|
||||
union { double v; uint64_t u; } buf;
|
||||
if ( gzread ( fd, &buf.u, sizeof(double) ) != sizeof(double) ) {
|
||||
read_error = true ;
|
||||
}
|
||||
if ( sgIsBigEndian() ) {
|
||||
sgEndianSwap( (uint64_t *)var);
|
||||
sgEndianSwap( &buf.u );
|
||||
}
|
||||
*var = buf.v;
|
||||
}
|
||||
|
||||
|
||||
void sgWriteDouble ( gzFile fd, const double var )
|
||||
{
|
||||
union { double v; uint64_t u; } buf;
|
||||
buf.v = var;
|
||||
if ( sgIsBigEndian() ) {
|
||||
sgEndianSwap( (uint64_t *)&var);
|
||||
sgEndianSwap( &buf.u );
|
||||
}
|
||||
if ( gzwrite ( fd, (void *)(&var), sizeof(double) ) != sizeof(double) ) {
|
||||
if ( gzwrite ( fd, (void *)(&buf.u), sizeof(double) ) != sizeof(double) ) {
|
||||
write_error = true ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/bucket/newbucket.hxx>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -12,6 +12,7 @@ class TcpServer
|
||||
{
|
||||
public:
|
||||
TcpServer();
|
||||
~TcpServer();
|
||||
bool open();
|
||||
bool process();
|
||||
bool close();
|
||||
@@ -25,6 +26,11 @@ TcpServer::TcpServer()
|
||||
channel = new SGSocket( "", "5500", "tcp" );
|
||||
}
|
||||
|
||||
TcpServer::~TcpServer()
|
||||
{
|
||||
delete channel;
|
||||
}
|
||||
|
||||
bool
|
||||
TcpServer::open()
|
||||
{
|
||||
|
||||
@@ -2,11 +2,9 @@ includedir = @includedir@/magvar
|
||||
|
||||
lib_LIBRARIES = libsgmagvar.a
|
||||
|
||||
include_HEADERS = magvar.hxx
|
||||
include_HEADERS = magvar.hxx coremag.hxx
|
||||
|
||||
libsgmagvar_a_SOURCES = \
|
||||
coremag.hxx coremag.cxx \
|
||||
magvar.cxx
|
||||
libsgmagvar_a_SOURCES = coremag.cxx magvar.cxx
|
||||
|
||||
noinst_PROGRAMS = testmagvar
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ check_PROGRAMS = SGMathTest SGGeometryTest
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
SGMathTest_SOURCES = SGMathTest.cxx
|
||||
SGMathTest_LDADD = libsgmath.a $(base_LIBS)
|
||||
SGMathTest_LDADD = libsgmath.a -lsgstructure $(base_LIBS)
|
||||
|
||||
SGGeometryTest_SOURCES = SGGeometryTest.cxx
|
||||
SGGeometryTest_LDADD = libsgmath.a $(base_LIBS)
|
||||
SGGeometryTest_LDADD = libsgmath.a -lsgstructure $(base_LIBS)
|
||||
|
||||
lib_LIBRARIES = libsgmath.a
|
||||
|
||||
@@ -42,7 +42,8 @@ include_HEADERS = \
|
||||
SGTriangle.hxx \
|
||||
SGVec2.hxx \
|
||||
SGVec3.hxx \
|
||||
SGVec4.hxx
|
||||
SGVec4.hxx \
|
||||
beziercurve.hxx
|
||||
|
||||
libsgmath_a_SOURCES = \
|
||||
interpolater.cxx \
|
||||
|
||||
+52
-1
@@ -25,6 +25,20 @@ public:
|
||||
_min(SGLimits<T>::max(), SGLimits<T>::max(), SGLimits<T>::max()),
|
||||
_max(-SGLimits<T>::max(), -SGLimits<T>::max(), -SGLimits<T>::max())
|
||||
{ }
|
||||
SGBox(const SGVec3<T>& pt) :
|
||||
_min(pt),
|
||||
_max(pt)
|
||||
{ }
|
||||
SGBox(const SGVec3<T>& min, const SGVec3<T>& max) :
|
||||
_min(min),
|
||||
_max(max)
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGBox(const SGBox<S>& box) :
|
||||
_min(box.getMin()),
|
||||
_max(box.getMax())
|
||||
{ }
|
||||
|
||||
void setMin(const SGVec3<T>& min)
|
||||
{ _min = min; }
|
||||
const SGVec3<T>& getMin() const
|
||||
@@ -35,6 +49,29 @@ public:
|
||||
const SGVec3<T>& getMax() const
|
||||
{ return _max; }
|
||||
|
||||
SGVec3<T> getCorner(unsigned i) const
|
||||
{ return SGVec3<T>((i&1) ? _min[0] : _max[0],
|
||||
(i&2) ? _min[1] : _max[1],
|
||||
(i&4) ? _min[2] : _max[2]); }
|
||||
|
||||
template<typename S>
|
||||
SGVec3<T> getNearestCorner(const SGVec3<S>& pt) const
|
||||
{
|
||||
SGVec3<T> center = getCenter();
|
||||
return SGVec3<T>((pt[0] <= center[0]) ? _min[0] : _max[0],
|
||||
(pt[1] <= center[1]) ? _min[1] : _max[1],
|
||||
(pt[2] <= center[2]) ? _min[2] : _max[2]);
|
||||
}
|
||||
template<typename S>
|
||||
SGVec3<T> getFarestCorner(const SGVec3<S>& pt) const
|
||||
{
|
||||
SGVec3<T> center = getCenter();
|
||||
return SGVec3<T>((pt[0] > center[0]) ? _min[0] : _max[0],
|
||||
(pt[1] > center[1]) ? _min[1] : _max[1],
|
||||
(pt[2] > center[2]) ? _min[2] : _max[2]);
|
||||
}
|
||||
|
||||
|
||||
// Only works for floating point types
|
||||
SGVec3<T> getCenter() const
|
||||
{ return T(0.5)*(_min + _max); }
|
||||
@@ -42,6 +79,8 @@ public:
|
||||
// Only valid for nonempty boxes
|
||||
SGVec3<T> getSize() const
|
||||
{ return _max - _min; }
|
||||
SGVec3<T> getHalfSize() const
|
||||
{ return T(0.5)*getSize(); }
|
||||
|
||||
T getVolume() const
|
||||
{
|
||||
@@ -83,7 +122,7 @@ public:
|
||||
// Note that this only works if the box is nonmepty
|
||||
unsigned getBroadestAxis() const
|
||||
{
|
||||
SGVec3d size = getSize();
|
||||
SGVec3<T> size = getSize();
|
||||
if (size[1] <= size[0] && size[2] <= size[0])
|
||||
return 0;
|
||||
else if (size[2] <= size[1])
|
||||
@@ -92,6 +131,18 @@ public:
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Note that this only works if the box is nonmepty
|
||||
unsigned getSmallestAxis() const
|
||||
{
|
||||
SGVec3<T> size = getSize();
|
||||
if (size[1] >= size[0] && size[2] >= size[0])
|
||||
return 0;
|
||||
else if (size[2] >= size[1])
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
private:
|
||||
SGVec3<T> _min;
|
||||
SGVec3<T> _max;
|
||||
|
||||
@@ -79,6 +79,8 @@ public:
|
||||
static double courseDeg(const SGGeoc& from, const SGGeoc& to);
|
||||
static double distanceM(const SGGeoc& from, const SGGeoc& to);
|
||||
|
||||
// Compare two geocentric positions for equality
|
||||
bool operator == ( const SGGeoc & other ) const;
|
||||
private:
|
||||
/// This one is private since construction is not unique if you do
|
||||
/// not know the units of the arguments, use the factory methods for
|
||||
@@ -323,6 +325,15 @@ SGGeoc::distanceM(const SGGeoc& from, const SGGeoc& to)
|
||||
return SGGeodesy::distanceM(from, to);
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
SGGeoc::operator == ( const SGGeoc & other ) const
|
||||
{
|
||||
return _lon == other._lon &&
|
||||
_lat == other._lat &&
|
||||
_radius == other._radius;
|
||||
}
|
||||
|
||||
/// Output to an ostream
|
||||
template<typename char_type, typename traits_type>
|
||||
inline
|
||||
|
||||
+11
-7
@@ -17,22 +17,24 @@
|
||||
|
||||
#include "SGMath.hxx"
|
||||
|
||||
osg::Matrix SGGeod::makeSimulationFrameRelative()
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
|
||||
osg::Matrix SGGeod::makeSimulationFrameRelative() const
|
||||
{
|
||||
SGQuatd hlOr = SGQuatd::fromLonLat(*this);
|
||||
return osg::Matrix(hlOr.osg());
|
||||
return osg::Matrix(toOsg(hlOr));
|
||||
}
|
||||
|
||||
osg::Matrix SGGeod::makeSimulationFrame()
|
||||
osg::Matrix SGGeod::makeSimulationFrame() const
|
||||
{
|
||||
osg::Matrix result(makeSimulationFrameRelative());
|
||||
SGVec3d coord;
|
||||
SGGeodesy::SGGeodToCart(*this, coord);
|
||||
result.setTrans(coord.osg());
|
||||
result.setTrans(toOsg(coord));
|
||||
return result;
|
||||
}
|
||||
|
||||
osg::Matrix SGGeod::makeZUpFrameRelative()
|
||||
osg::Matrix SGGeod::makeZUpFrameRelative() const
|
||||
{
|
||||
osg::Matrix result(makeSimulationFrameRelative());
|
||||
// 180 degree rotation around Y axis
|
||||
@@ -41,11 +43,13 @@ osg::Matrix SGGeod::makeZUpFrameRelative()
|
||||
return result;
|
||||
}
|
||||
|
||||
osg::Matrix SGGeod::makeZUpFrame()
|
||||
osg::Matrix SGGeod::makeZUpFrame() const
|
||||
{
|
||||
osg::Matrix result(makeZUpFrameRelative());
|
||||
SGVec3d coord;
|
||||
SGGeodesy::SGGeodToCart(*this, coord);
|
||||
result.setTrans(coord.osg());
|
||||
result.setTrans(toOsg(coord));
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+40
-6
@@ -20,7 +20,9 @@
|
||||
|
||||
#include <simgear/constants.h>
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Matrix>
|
||||
#endif
|
||||
|
||||
// #define SG_GEOD_NATIVE_DEGREE
|
||||
|
||||
@@ -42,6 +44,10 @@ public:
|
||||
static SGGeod fromRadM(double lon, double lat, double elevation);
|
||||
/// Factory from angular values in degrees and elevation in m
|
||||
static SGGeod fromDegM(double lon, double lat, double elevation);
|
||||
/// Factory from an other SGGeod and a different elevation in m
|
||||
static SGGeod fromGeodM(const SGGeod& geod, double elevation);
|
||||
/// Factory from an other SGGeod and a different elevation in ft
|
||||
static SGGeod fromGeodFt(const SGGeod& geod, double elevation);
|
||||
/// Factory to convert position from a cartesian position assumed to be
|
||||
/// in wgs84 measured in meters
|
||||
/// Note that this conversion is relatively expensive to compute
|
||||
@@ -80,25 +86,30 @@ public:
|
||||
/// Set the geodetic elevation from the argument given in feet
|
||||
void setElevationFt(double elevation);
|
||||
|
||||
// Compare two geodetic positions for equality
|
||||
bool operator == ( const SGGeod & other ) const;
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
// Create a local coordinate frame in the earth-centered frame of
|
||||
// reference. X points north, Z points down.
|
||||
// makeSimulationFrameRelative() only includes rotation.
|
||||
|
||||
osg::Matrix makeSimulationFrameRelative();
|
||||
osg::Matrix makeSimulationFrame();
|
||||
osg::Matrix makeSimulationFrameRelative() const;
|
||||
osg::Matrix makeSimulationFrame() const;
|
||||
|
||||
// Create a Z-up local coordinate frame in the earth-centered frame
|
||||
// of reference. This is what scenery models, etc. expect.
|
||||
// makeZUpFrameRelative() only includes rotation.
|
||||
osg::Matrix makeZUpFrameRelative();
|
||||
osg::Matrix makeZUpFrame();
|
||||
osg::Matrix makeZUpFrameRelative() const;
|
||||
osg::Matrix makeZUpFrame() const;
|
||||
#endif
|
||||
private:
|
||||
/// This one is private since construction is not unique if you do
|
||||
/// not know the units of the arguments. Use the factory methods for
|
||||
/// that purpose
|
||||
SGGeod(double lon, double lat, double elevation);
|
||||
|
||||
/// The actual data, angles in degree, elevation in meters
|
||||
//// FIXME: wrong comment!
|
||||
/// The actual data, angles in degrees, elevation in meters
|
||||
/// The rationale for storing the values in degrees is that most code places
|
||||
/// in flightgear/terragear use degrees as a nativ input and output value.
|
||||
/// The places where it makes sense to use radians is when we convert
|
||||
@@ -192,6 +203,20 @@ SGGeod::fromDegM(double lon, double lat, double elevation)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
SGGeod
|
||||
SGGeod::fromGeodM(const SGGeod& geod, double elevation)
|
||||
{
|
||||
return SGGeod(geod._lon, geod._lat, elevation);
|
||||
}
|
||||
|
||||
inline
|
||||
SGGeod
|
||||
SGGeod::fromGeodFt(const SGGeod& geod, double elevation)
|
||||
{
|
||||
return SGGeod(geod._lon, geod._lat, elevation*SG_FEET_TO_METER);
|
||||
}
|
||||
|
||||
inline
|
||||
SGGeod
|
||||
SGGeod::fromCart(const SGVec3<double>& cart)
|
||||
@@ -328,6 +353,15 @@ SGGeod::setElevationFt(double elevation)
|
||||
_elevation = elevation*SG_FEET_TO_METER;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
SGGeod::operator == ( const SGGeod & other ) const
|
||||
{
|
||||
return _lon == other._lon &&
|
||||
_lat == other._lat &&
|
||||
_elevation == other._elevation;
|
||||
}
|
||||
|
||||
/// Output to an ostream
|
||||
template<typename char_type, typename traits_type>
|
||||
inline
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include "SGMath.hxx"
|
||||
|
||||
// These are hard numbers from the WGS84 standard. DON'T MODIFY
|
||||
@@ -56,7 +57,7 @@ const double SGGeodesy::POLRAD = _POLRAD;
|
||||
#define E2 fabs(1 - _SQUASH*_SQUASH)
|
||||
static double a = _EQURAD;
|
||||
static double ra2 = 1/(_EQURAD*_EQURAD);
|
||||
static double e = sqrt(E2);
|
||||
//static double e = sqrt(E2);
|
||||
static double e2 = E2;
|
||||
static double e4 = E2*E2;
|
||||
|
||||
@@ -78,11 +79,30 @@ SGGeodesy::SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod)
|
||||
double Y = cart(1);
|
||||
double Z = cart(2);
|
||||
double XXpYY = X*X+Y*Y;
|
||||
if( XXpYY + Z*Z < 25 ) {
|
||||
// This function fails near the geocenter region, so catch that special case here.
|
||||
// Define the innermost sphere of small radius as earth center and return the
|
||||
// coordinates 0/0/-EQURAD. It may be any other place on geoide's surface,
|
||||
// the Northpole, Hawaii or Wentorf. This one was easy to code ;-)
|
||||
geod.setLongitudeRad( 0.0 );
|
||||
geod.setLongitudeRad( 0.0 );
|
||||
geod.setElevationM( -EQURAD );
|
||||
return;
|
||||
}
|
||||
|
||||
double sqrtXXpYY = sqrt(XXpYY);
|
||||
double p = XXpYY*ra2;
|
||||
double q = Z*Z*(1-e2)*ra2;
|
||||
double r = 1/6.0*(p+q-e4);
|
||||
double s = e4*p*q/(4*r*r*r);
|
||||
/*
|
||||
s*(2+s) is negative for s = [-2..0]
|
||||
slightly negative values for s due to floating point rounding errors
|
||||
cause nan for sqrt(s*(2+s))
|
||||
We can probably clamp the resulting parable to positive numbers
|
||||
*/
|
||||
if( s >= -2.0 && s <= 0.0 )
|
||||
s = 0.0;
|
||||
double t = pow(1+s+sqrt(s*(2+s)), 1/3.0);
|
||||
double u = r*(1+t+1/t);
|
||||
double v = sqrt(u*u+e4*q);
|
||||
@@ -314,7 +334,7 @@ static int _geo_inverse_wgs_84( double lat1, double lon1, double lat2,
|
||||
double sinphi2 = sin(phi2), cosphi2 = cos(phi2);
|
||||
|
||||
if( (fabs(lat1-lat2) < testv &&
|
||||
( fabs(lon1-lon2) < testv) || fabs(lat1-90.0) < testv ) )
|
||||
( fabs(lon1-lon2) < testv)) || (fabs(lat1-90.0) < testv ) )
|
||||
{
|
||||
// TWO STATIONS ARE IDENTICAL : SET DISTANCE & AZIMUTHS TO ZERO */
|
||||
*az1 = 0.0; *az2 = 0.0; *s = 0.0;
|
||||
@@ -423,6 +443,40 @@ SGGeodesy::inverse(const SGGeod& p1, const SGGeod& p2, double& course1,
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
double
|
||||
SGGeodesy::courseDeg(const SGGeod& p1, const SGGeod& p2)
|
||||
{
|
||||
double course1, course2, distance;
|
||||
int r = _geo_inverse_wgs_84(p1.getLatitudeDeg(), p1.getLongitudeDeg(),
|
||||
p2.getLatitudeDeg(), p2.getLongitudeDeg(),
|
||||
&course1, &course2, &distance);
|
||||
if (r != 0) {
|
||||
throw sg_exception("SGGeodesy::courseDeg, unable to compute course");
|
||||
}
|
||||
|
||||
return course1;
|
||||
}
|
||||
|
||||
double
|
||||
SGGeodesy::distanceM(const SGGeod& p1, const SGGeod& p2)
|
||||
{
|
||||
double course1, course2, distance;
|
||||
int r = _geo_inverse_wgs_84(p1.getLatitudeDeg(), p1.getLongitudeDeg(),
|
||||
p2.getLatitudeDeg(), p2.getLongitudeDeg(),
|
||||
&course1, &course2, &distance);
|
||||
if (r != 0) {
|
||||
throw sg_exception("SGGeodesy::distanceM, unable to compute distance");
|
||||
}
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
double
|
||||
SGGeodesy::distanceNm(const SGGeod& from, const SGGeod& to)
|
||||
{
|
||||
return distanceM(from, to) * SG_METER_TO_NM;
|
||||
}
|
||||
|
||||
/// Geocentric routines
|
||||
|
||||
void
|
||||
@@ -486,7 +540,7 @@ SGGeodesy::courseRad(const SGGeoc& from, const SGGeoc& to)
|
||||
}
|
||||
|
||||
double
|
||||
SGGeodesy::distanceM(const SGGeoc& from, const SGGeoc& to)
|
||||
SGGeodesy::distanceRad(const SGGeoc& from, const SGGeoc& to)
|
||||
{
|
||||
// d = 2*asin(sqrt((sin((lat1-lat2)/2))^2 +
|
||||
// cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2))
|
||||
@@ -496,5 +550,12 @@ SGGeodesy::distanceM(const SGGeoc& from, const SGGeoc& to)
|
||||
double tmp2 = sin(0.5*(from.getLongitudeRad() - to.getLongitudeRad()));
|
||||
double square = tmp1*tmp1 + cosLatFrom*cosLatTo*tmp2*tmp2;
|
||||
double s = SGMiscd::min(sqrt(SGMiscd::max(square, 0)), 1);
|
||||
return 2 * asin(s) * SG_RAD_TO_NM * SG_NM_TO_METER;
|
||||
return 2 * asin(s);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
SGGeodesy::distanceM(const SGGeoc& from, const SGGeoc& to)
|
||||
{
|
||||
return distanceRad(from, to) * SG_RAD_TO_NM * SG_NM_TO_METER;
|
||||
}
|
||||
|
||||
@@ -53,10 +53,15 @@ public:
|
||||
static bool inverse(const SGGeod& p1, const SGGeod& p2, double& course1,
|
||||
double& course2, double& distance);
|
||||
|
||||
static double courseDeg(const SGGeod& from, const SGGeod& to);
|
||||
static double distanceM(const SGGeod& from, const SGGeod& to);
|
||||
static double distanceNm(const SGGeod& from, const SGGeod& to);
|
||||
|
||||
// Geocentric course/distance computation
|
||||
static void advanceRadM(const SGGeoc& geoc, double course, double distance,
|
||||
SGGeoc& result);
|
||||
static double courseRad(const SGGeoc& from, const SGGeoc& to);
|
||||
static double distanceRad(const SGGeoc& from, const SGGeoc& to);
|
||||
static double distanceM(const SGGeoc& from, const SGGeoc& to);
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,102 @@ SGVec3<T> rndVec3(void)
|
||||
return SGVec3<T>(sg_random(), sg_random(), sg_random());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
TriangleClosestPointIntersectionTest(void)
|
||||
{
|
||||
unsigned nTests = 100000;
|
||||
unsigned failedCount = 0;
|
||||
for (unsigned i = 0; i < nTests; ++i) {
|
||||
// test triangle
|
||||
SGTriangle<T> triangle(rndVec3<T>(), rndVec3<T>(), rndVec3<T>());
|
||||
T triangleEps = 100*SGLimits<T>::epsilon();
|
||||
|
||||
// generate random point in the triangle
|
||||
T u = 4*sg_random() - 2;
|
||||
T v = 4*sg_random() - 2;
|
||||
if (1 < u + v) {
|
||||
v = T(0.5)*(v + 1 - u);
|
||||
u = 1 - v;
|
||||
}
|
||||
u = SGMisc<T>::clip(u, 0, 1);
|
||||
v = SGMisc<T>::clip(v, 0, 1);
|
||||
|
||||
SGVec3<T> testClosest;
|
||||
testClosest = triangle.getBaseVertex();
|
||||
testClosest += u*triangle.getEdge(0) + v*triangle.getEdge(1);
|
||||
|
||||
SGVec3<T> n = triangle.getNormal();
|
||||
SGVec3<T> e0 = triangle.getEdge(0);
|
||||
SGVec3<T> e1 = triangle.getEdge(1);
|
||||
|
||||
// The normals to the edges
|
||||
SGVec3<T> a0 = cross(e0, n);
|
||||
SGVec3<T> a1 = cross(e1 - e0, n);
|
||||
SGVec3<T> a2 = cross(n, e1);
|
||||
|
||||
SGVec3<T> testPoint = testClosest;
|
||||
// Ok, if we are at some edge, go perpandicular to the triangle away
|
||||
if (u == 0) {
|
||||
if (v == 0) {
|
||||
testPoint += sg_random()*a0 + sg_random()*a2;
|
||||
} else if (v == 1) {
|
||||
testPoint += sg_random()*a1 + sg_random()*a2;
|
||||
} else {
|
||||
testPoint += sg_random()*a2;
|
||||
}
|
||||
} else if (u == 1) {
|
||||
testPoint += sg_random()*a0 + sg_random()*a1;
|
||||
} else {
|
||||
if (v == 0) {
|
||||
testPoint += sg_random()*a0;
|
||||
} else if (u + v == 1) {
|
||||
testPoint += sg_random()*a1;
|
||||
}
|
||||
}
|
||||
testPoint += (2*sg_random() - 1)*n;
|
||||
|
||||
// Test the closest point function
|
||||
SGVec3<T> closest = closestPoint(triangle, testPoint);
|
||||
if (!equivalent(closest, testClosest, triangleEps)) {
|
||||
std::cout << "Failed closest point test #" << i
|
||||
<< ": not equivalent!\nu = "
|
||||
<< u << ", v = " << v
|
||||
<< "\ntestPoint = " << testPoint
|
||||
<< ", testClosest = " << testClosest
|
||||
<< ", closest = " << closest << "\n"
|
||||
<< triangle << std::endl;
|
||||
++failedCount;
|
||||
}
|
||||
|
||||
// Test the triangle sphere intersection
|
||||
SGSphere<T> sphere(testPoint, sg_random());
|
||||
bool exactIntersection = intersects(sphere, testClosest);
|
||||
// bool exactIntersection = intersects(sphere, closest);
|
||||
bool sphereTriangleIntersection = intersects(sphere, triangle);
|
||||
|
||||
if (sphereTriangleIntersection != exactIntersection) {
|
||||
std::cout << "Failed triangle sphere intersection test #" << i
|
||||
<< ": not equivalent!\nu = "
|
||||
<< u << ", v = " << v
|
||||
<< "\ntestPoint = " << testPoint
|
||||
<< ", testClosest = " << testClosest
|
||||
<< ", closest = " << closest << "\n"
|
||||
<< triangle << std::endl;
|
||||
++failedCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (nTests < 100*failedCount) {
|
||||
std::cout << "Failed box line intersection tests: " << failedCount
|
||||
<< " tests out of " << nTests
|
||||
<< " went wrong. Abort!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
TriangleLineIntersectionTest(void)
|
||||
@@ -44,6 +140,8 @@ TriangleLineIntersectionTest(void)
|
||||
|
||||
SGTriangle<T> tri(v0, v1, v2);
|
||||
|
||||
T triangleEps = 100*SGLimits<T>::epsilon();
|
||||
|
||||
// generate random coeficients
|
||||
T u = 4*sg_random() - 2;
|
||||
T v = 4*sg_random() - 2;
|
||||
@@ -59,7 +157,7 @@ TriangleLineIntersectionTest(void)
|
||||
|
||||
if (intersects(isectres, tri, lineSegment)) {
|
||||
if (0 <= u && 0 <= v && u+v <= 1 && 0 <= t && t <= 1) {
|
||||
if (!equivalent(isectres, isectpt)) {
|
||||
if (!equivalent(isectres, isectpt, triangleEps)) {
|
||||
std::cout << "Failed line segment intersection test #" << i
|
||||
<< ": not equivalent!\nu = "
|
||||
<< u << ", v = " << v << ", t = " << t
|
||||
@@ -87,7 +185,7 @@ TriangleLineIntersectionTest(void)
|
||||
ray.set(isectpt - t*dir, dir);
|
||||
if (intersects(isectres, tri, ray)) {
|
||||
if (0 <= u && 0 <= v && u+v <= 1 && 0 <= t) {
|
||||
if (!equivalent(isectres, isectpt)) {
|
||||
if (!equivalent(isectres, isectpt, triangleEps)) {
|
||||
std::cout << "Failed ray intersection test #" << i
|
||||
<< ": not equivalent!\nu = "
|
||||
<< u << ", v = " << v << ", t = " << t
|
||||
@@ -422,6 +520,13 @@ main(void)
|
||||
<< "Some of these tests can fail due to roundoff problems...\n"
|
||||
<< "Dont worry if only a few of them fail..." << std::endl;
|
||||
|
||||
sg_srandom(17);
|
||||
|
||||
if (!TriangleClosestPointIntersectionTest<float>())
|
||||
return EXIT_FAILURE;
|
||||
if (!TriangleClosestPointIntersectionTest<double>())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!TriangleLineIntersectionTest<float>())
|
||||
return EXIT_FAILURE;
|
||||
if (!TriangleLineIntersectionTest<double>())
|
||||
|
||||
+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
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -20,7 +20,21 @@
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
intersects(const SGBox<T>& box, const SGSphere<T>& sphere)
|
||||
intersects(const SGSphere<T>& s1, const SGSphere<T>& s2)
|
||||
{
|
||||
if (s1.empty())
|
||||
return false;
|
||||
if (s2.empty())
|
||||
return false;
|
||||
|
||||
T dist = s1.getRadius() + s2.getRadius();
|
||||
return distSqr(s1.getCenter(), s2.getCenter()) <= dist*dist;
|
||||
}
|
||||
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGBox<T1>& box, const SGSphere<T2>& sphere)
|
||||
{
|
||||
if (sphere.empty())
|
||||
return false;
|
||||
@@ -45,15 +59,15 @@ intersects(const SGBox<T>& box, const SGSphere<T>& sphere)
|
||||
return true;
|
||||
}
|
||||
// make it symmetric
|
||||
template<typename T>
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGSphere<T>& sphere, const SGBox<T>& box)
|
||||
intersects(const SGSphere<T1>& sphere, const SGBox<T2>& box)
|
||||
{ return intersects(box, sphere); }
|
||||
|
||||
|
||||
template<typename T>
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGVec3<T>& v, const SGBox<T>& box)
|
||||
intersects(const SGVec3<T1>& v, const SGBox<T2>& box)
|
||||
{
|
||||
if (v[0] < box.getMin()[0])
|
||||
return false;
|
||||
@@ -69,9 +83,9 @@ intersects(const SGVec3<T>& v, const SGBox<T>& box)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
template<typename T>
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGBox<T>& box, const SGVec3<T>& v)
|
||||
intersects(const SGBox<T1>& box, const SGVec3<T2>& v)
|
||||
{ return intersects(v, box); }
|
||||
|
||||
|
||||
@@ -529,13 +543,427 @@ template<typename T>
|
||||
inline bool
|
||||
intersects(const SGTriangle<T>& tri, const SGLineSegment<T>& lineSegment, T eps = 0)
|
||||
{
|
||||
// FIXME: for now just wrap the othr method. When that has prooven
|
||||
// FIXME: for now just wrap the other method. When that has prooven
|
||||
// well optimized, implement that special case
|
||||
SGVec3<T> dummy;
|
||||
return intersects(dummy, tri, lineSegment, eps);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline SGVec3<T>
|
||||
closestPoint(const SGTriangle<T>& tri, const SGVec3<T>& p)
|
||||
{
|
||||
// This method minimizes the distance function Q(u, v) = || p - x ||
|
||||
// where x is a point in the trialgle given by the vertices v_i
|
||||
// x = v_0 + u*(v_1 - v_0) + v*(v_2 - v_0)
|
||||
// The theoretical analysis is somehow too long for a comment.
|
||||
// May be it is sufficient to see that this code passes all the tests.
|
||||
|
||||
SGVec3<T> off = tri.getBaseVertex() - p;
|
||||
T a = dot(tri.getEdge(0), tri.getEdge(0));
|
||||
T b = dot(tri.getEdge(0), tri.getEdge(1));
|
||||
T c = dot(tri.getEdge(1), tri.getEdge(1));
|
||||
T d = dot(tri.getEdge(0), off);
|
||||
T e = dot(tri.getEdge(1), off);
|
||||
|
||||
T det = a*c - b*b;
|
||||
|
||||
T u = b*e - c*d;
|
||||
T v = b*d - a*e;
|
||||
|
||||
/*
|
||||
// Regions
|
||||
// \2|
|
||||
// \|
|
||||
// |\
|
||||
// 3 |0\ 1
|
||||
//----------
|
||||
// 4 | 5 \ 6
|
||||
*/
|
||||
|
||||
if (u + v <= det) {
|
||||
if (u < 0) {
|
||||
if (v < 0) {
|
||||
// region 4
|
||||
if (d < 0) {
|
||||
if (a <= -d) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0);
|
||||
}
|
||||
} else {
|
||||
if (0 < e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else if (c <= -e) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getBaseVertex() + tri.getEdge(1);
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
return tri.getBaseVertex() + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// region 3
|
||||
if (0 <= e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else if (c <= -e) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getBaseVertex() + tri.getEdge(1);
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
return tri.getBaseVertex() + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
} else if (v < 0) {
|
||||
// region 5
|
||||
if (0 <= d) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else if (a <= -d) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0);
|
||||
}
|
||||
} else {
|
||||
// region 0
|
||||
if (det <= SGLimits<T>::min()) {
|
||||
u = 0;
|
||||
v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else {
|
||||
T invDet = 1/det;
|
||||
u *= invDet;
|
||||
v *= invDet;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (u < 0) {
|
||||
// region 2
|
||||
T tmp0 = b + d;
|
||||
T tmp1 = c + e;
|
||||
if (tmp0 < tmp1) {
|
||||
T numer = tmp1 - tmp0;
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else {
|
||||
u = numer/denom;
|
||||
v = 1 - u;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
|
||||
}
|
||||
} else {
|
||||
if (tmp1 <= 0) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getBaseVertex() + tri.getEdge(1);
|
||||
} else if (0 <= e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
return tri.getBaseVertex() + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
} else if (v < 0) {
|
||||
// region 6
|
||||
T tmp0 = b + e;
|
||||
T tmp1 = a + d;
|
||||
if (tmp0 < tmp1) {
|
||||
T numer = tmp1 - tmp0;
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getBaseVertex() + tri.getEdge(1);
|
||||
} else {
|
||||
v = numer/denom;
|
||||
u = 1 - v;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
|
||||
}
|
||||
} else {
|
||||
if (tmp1 < 0) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else if (0 <= d) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex();
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// region 1
|
||||
T numer = c + e - b - d;
|
||||
if (numer <= 0) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
return tri.getVertex(2);
|
||||
} else {
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
return tri.getBaseVertex() + tri.getEdge(0);
|
||||
} else {
|
||||
u = numer/denom;
|
||||
v = 1 - u;
|
||||
return tri.getBaseVertex() + u*tri.getEdge(0) + v*tri.getEdge(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T>
|
||||
inline SGVec3<T>
|
||||
closestPoint(const SGVec3<T>& p, const SGTriangle<T>& tri)
|
||||
{ return closestPoint(tri, p); }
|
||||
|
||||
template<typename T, typename T2>
|
||||
inline bool
|
||||
intersects(const SGTriangle<T>& tri, const SGSphere<T2>& sphere)
|
||||
{
|
||||
// This method minimizes the distance function Q(u, v) = || p - x ||
|
||||
// where x is a point in the trialgle given by the vertices v_i
|
||||
// x = v_0 + u*(v_1 - v_0) + v*(v_2 - v_0)
|
||||
// The theoretical analysis is somehow too long for a comment.
|
||||
// May be it is sufficient to see that this code passes all the tests.
|
||||
|
||||
SGVec3<T> off = tri.getBaseVertex() - SGVec3<T>(sphere.getCenter());
|
||||
T baseDist2 = dot(off, off);
|
||||
T a = dot(tri.getEdge(0), tri.getEdge(0));
|
||||
T b = dot(tri.getEdge(0), tri.getEdge(1));
|
||||
T c = dot(tri.getEdge(1), tri.getEdge(1));
|
||||
T d = dot(tri.getEdge(0), off);
|
||||
T e = dot(tri.getEdge(1), off);
|
||||
|
||||
T det = a*c - b*b;
|
||||
|
||||
T u = b*e - c*d;
|
||||
T v = b*d - a*e;
|
||||
|
||||
/*
|
||||
// Regions
|
||||
// \2|
|
||||
// \|
|
||||
// |\
|
||||
// 3 |0\ 1
|
||||
//----------
|
||||
// 4 | 5 \ 6
|
||||
*/
|
||||
|
||||
if (u + v <= det) {
|
||||
if (u < 0) {
|
||||
if (v < 0) {
|
||||
// region 4
|
||||
if (d < 0) {
|
||||
if (a <= -d) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
T sqrDist = d*u + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
} else {
|
||||
if (0 < e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else if (c <= -e) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
T sqrDist = e*v + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// region 3
|
||||
if (0 <= e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else if (c <= -e) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
T sqrDist = e*v + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else if (v < 0) {
|
||||
// region 5
|
||||
if (0 <= d) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else if (a <= -d) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
T sqrDist = d*u + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
} else {
|
||||
// region 0
|
||||
if (det <= SGLimits<T>::min()) {
|
||||
// sqrDist = baseDist2;
|
||||
u = 0;
|
||||
v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else {
|
||||
T invDet = 1/det;
|
||||
u *= invDet;
|
||||
v *= invDet;
|
||||
T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e) + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (u < 0) {
|
||||
// region 2
|
||||
T tmp0 = b + d;
|
||||
T tmp1 = c + e;
|
||||
if (tmp0 < tmp1) {
|
||||
T numer = tmp1 - tmp0;
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
u = numer/denom;
|
||||
v = 1 - u;
|
||||
T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e) + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
} else {
|
||||
if (tmp1 <= 0) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else if (0 <= e) {
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else {
|
||||
// u = 0;
|
||||
v = -e/c;
|
||||
T sqrDist = e*v + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else if (v < 0) {
|
||||
// region 6
|
||||
T tmp0 = b + e;
|
||||
T tmp1 = a + d;
|
||||
if (tmp0 < tmp1) {
|
||||
T numer = tmp1 - tmp0;
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
v = numer/denom;
|
||||
u = 1 - v;
|
||||
T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e)+baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
} else {
|
||||
if (tmp1 < 0) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else if (0 <= d) {
|
||||
// sqrDist = baseDist2;
|
||||
// u = 0;
|
||||
// v = 0;
|
||||
return baseDist2 <= sphere.getRadius2();
|
||||
} else {
|
||||
u = -d/a;
|
||||
// v = 0;
|
||||
T sqrDist = d*u + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// region 1
|
||||
T numer = c + e - b - d;
|
||||
if (numer <= 0) {
|
||||
// u = 0;
|
||||
// v = 1;
|
||||
T sqrDist = c + 2*e + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
T denom = a - 2*b + c;
|
||||
if (denom <= numer) {
|
||||
// u = 1;
|
||||
// v = 0;
|
||||
T sqrDist = a + 2*d + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
} else {
|
||||
u = numer/denom;
|
||||
v = 1 - u;
|
||||
T sqrDist = u*(a*u + b*v + 2*d) + v*(b*u + c*v + 2*e) + baseDist2;
|
||||
return sqrDist <= sphere.getRadius2();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGSphere<T1>& sphere, const SGTriangle<T2>& tri)
|
||||
{ return intersects(tri, sphere); }
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
intersects(const SGVec3<T>& v, const SGSphere<T>& sphere)
|
||||
@@ -557,9 +985,9 @@ intersects(const SGBox<T>& box, const SGLineSegment<T>& lineSegment)
|
||||
// See Tomas Akeniene - Moeller/Eric Haines: Real Time Rendering
|
||||
|
||||
SGVec3<T> c = lineSegment.getCenter() - box.getCenter();
|
||||
SGVec3<T> w = 0.5*lineSegment.getDirection();
|
||||
SGVec3<T> w = T(0.5)*lineSegment.getDirection();
|
||||
SGVec3<T> v(fabs(w.x()), fabs(w.y()), fabs(w.z()));
|
||||
SGVec3<T> h = 0.5*box.getSize();
|
||||
SGVec3<T> h = T(0.5)*box.getSize();
|
||||
|
||||
if (fabs(c[0]) > v[0] + h[0])
|
||||
return false;
|
||||
@@ -624,4 +1052,26 @@ inline bool
|
||||
intersects(const SGRay<T>& ray, const SGBox<T>& box)
|
||||
{ return intersects(box, ray); }
|
||||
|
||||
template<typename T1, typename T2>
|
||||
inline bool
|
||||
intersects(const SGBox<T1>& box1, const SGBox<T2>& box2)
|
||||
{
|
||||
if (box2.getMax()[0] < box1.getMin()[0])
|
||||
return false;
|
||||
if (box1.getMax()[0] < box2.getMin()[0])
|
||||
return false;
|
||||
|
||||
if (box2.getMax()[1] < box1.getMin()[1])
|
||||
return false;
|
||||
if (box1.getMax()[1] < box2.getMin()[1])
|
||||
return false;
|
||||
|
||||
if (box2.getMax()[2] < box1.getMin()[2])
|
||||
return false;
|
||||
if (box1.getMax()[2] < box2.getMin()[2])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,11 @@ public:
|
||||
_start(start),
|
||||
_direction(end - start)
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGLineSegment(const SGLineSegment<S>& lineSegment) :
|
||||
_start(lineSegment.getStart()),
|
||||
_direction(lineSegment.getDirection())
|
||||
{ }
|
||||
|
||||
void set(const SGVec3<T>& start, const SGVec3<T>& end)
|
||||
{ _start = start; _direction = end - start; }
|
||||
@@ -43,6 +48,14 @@ public:
|
||||
SGVec3<T> getCenter() const
|
||||
{ return _start + T(0.5)*_direction; }
|
||||
|
||||
SGLineSegment<T> transform(const SGMatrix<T>& matrix) const
|
||||
{
|
||||
SGLineSegment<T> lineSegment;
|
||||
lineSegment._start = matrix.xformPt(_start);
|
||||
lineSegment._direction = matrix.xformVec(_direction);
|
||||
return lineSegment;
|
||||
}
|
||||
|
||||
private:
|
||||
SGVec3<T> _start;
|
||||
SGVec3<T> _direction;
|
||||
|
||||
@@ -174,16 +174,22 @@ MatrixTest(void)
|
||||
// Create some test matrix
|
||||
SGVec3<T> v0(2, 7, 17);
|
||||
SGQuat<T> q0 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), normalize(v0));
|
||||
SGMatrix<T> m0;
|
||||
SGMatrix<T> m0 = SGMatrix<T>::unit();
|
||||
m0.postMultTranslate(v0);
|
||||
m0.postMultRotate(q0);
|
||||
|
||||
// Check the tqo forms of the inverse for that kind of special matrix
|
||||
SGMatrix<T> m1, m2;
|
||||
invert(m1, m0);
|
||||
m2 = transNeg(m0);
|
||||
// Check the three forms of the inverse for that kind of special matrix
|
||||
SGMatrix<T> m1 = SGMatrix<T>::unit();
|
||||
m1.preMultTranslate(-v0);
|
||||
m1.preMultRotate(inverse(q0));
|
||||
|
||||
SGMatrix<T> m2, m3;
|
||||
invert(m2, m0);
|
||||
m3 = transNeg(m0);
|
||||
if (!equivalent(m1, m2))
|
||||
return false;
|
||||
if (!equivalent(m2, m3))
|
||||
return false;
|
||||
|
||||
// Check matrix multiplication and inversion
|
||||
if (!equivalent(m0*m1, SGMatrix<T>::unit()))
|
||||
@@ -194,6 +200,10 @@ MatrixTest(void)
|
||||
return false;
|
||||
if (!equivalent(m2*m0, SGMatrix<T>::unit()))
|
||||
return false;
|
||||
if (!equivalent(m0*m3, SGMatrix<T>::unit()))
|
||||
return false;
|
||||
if (!equivalent(m3*m0, SGMatrix<T>::unit()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -202,10 +212,10 @@ bool
|
||||
GeodesyTest(void)
|
||||
{
|
||||
// We know that the values are on the order of 1
|
||||
double epsDeg = 10*SGLimits<double>::epsilon();
|
||||
double epsDeg = 10*360*SGLimits<double>::epsilon();
|
||||
// For the altitude values we need to tolerate relative errors in the order
|
||||
// of the radius
|
||||
double epsM = 1e6*SGLimits<double>::epsilon();
|
||||
double epsM = 10*6e6*SGLimits<double>::epsilon();
|
||||
|
||||
SGVec3<double> cart0, cart1;
|
||||
SGGeod geod0, geod1;
|
||||
|
||||
@@ -184,8 +184,15 @@ public:
|
||||
template<typename S>
|
||||
SGMatrix& preMultTranslate(const SGVec3<S>& t)
|
||||
{
|
||||
for (unsigned i = 0; i < SGMatrix<T>::nCols-1; ++i)
|
||||
(*this)(i,3) += T(t(i));
|
||||
for (unsigned i = 0; i < 3; ++i) {
|
||||
T tmp = T(t(i));
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
(*this)(i,0) += tmp*(*this)(3,0);
|
||||
(*this)(i,1) += tmp*(*this)(3,1);
|
||||
(*this)(i,2) += tmp*(*this)(3,2);
|
||||
(*this)(i,3) += tmp*(*this)(3,3);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template<typename S>
|
||||
@@ -193,7 +200,7 @@ public:
|
||||
{
|
||||
SGVec4<T> col3((*this)(0,3), (*this)(1,3), (*this)(2,3), (*this)(3,3));
|
||||
for (unsigned i = 0; i < SGMatrix<T>::nCols-1; ++i) {
|
||||
SGVec4<T> tmp((*this)(0,3), (*this)(1,3), (*this)(2,3), (*this)(3,3));
|
||||
SGVec4<T> tmp((*this)(0,i), (*this)(1,i), (*this)(2,i), (*this)(3,i));
|
||||
col3 += T(t(i))*tmp;
|
||||
}
|
||||
(*this)(0,3) = col3(0); (*this)(1,3) = col3(1);
|
||||
|
||||
@@ -23,14 +23,25 @@ class SGPlane {
|
||||
public:
|
||||
SGPlane()
|
||||
{ }
|
||||
SGPlane(const SGVec3<T>& normal, T dist) :
|
||||
SGPlane(const SGVec3<T>& normal, const T& dist) :
|
||||
_normal(normal), _dist(dist)
|
||||
{ }
|
||||
SGPlane(const SGVec3<T>& normal, const SGVec3<T>& point) :
|
||||
_normal(normal), _dist(-dot(normal, point))
|
||||
{ }
|
||||
SGPlane(const SGVec3<T> vertices[3]) :
|
||||
_normal(normalize(cross(vertices[1] - vertices[0],
|
||||
vertices[2] - vertices[0]))),
|
||||
_dist(-dot(_normal, vertices[0]))
|
||||
{ }
|
||||
SGPlane(const SGVec3<T>& v0, const SGVec3<T>& v1, const SGVec3<T>& v2) :
|
||||
_normal(normalize(cross(v1 - v0, v2 - v0))),
|
||||
_dist(-dot(_normal, v0))
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGPlane(const SGPlane<S>& plane) :
|
||||
_normal(plane.getNormal()), _dist(plane.getDist())
|
||||
{ }
|
||||
|
||||
void setNormal(const SGVec3<T>& normal)
|
||||
{ _normal = normal; }
|
||||
@@ -42,6 +53,10 @@ public:
|
||||
const T& getDist() const
|
||||
{ return _dist; }
|
||||
|
||||
/// Return a point on the plane
|
||||
SGVec3<T> getPointOnPlane() const
|
||||
{ return -_dist*_normal; }
|
||||
|
||||
/// That is the distance where we measure positive in direction of the normal
|
||||
T getPositiveDist() const
|
||||
{ return -_dist; }
|
||||
|
||||
+52
-110
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
// Copyright (C) 2006-2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -26,42 +26,13 @@
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Quat>
|
||||
#endif
|
||||
|
||||
/// Quaternion Class
|
||||
template<typename T>
|
||||
struct SGQuatStorage {
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[4]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[4]
|
||||
{ return _data; }
|
||||
|
||||
void osg() const
|
||||
{ }
|
||||
|
||||
private:
|
||||
T _data[4];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGQuatStorage<double> : public osg::Quat {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const double (&data(void) const)[4]
|
||||
{ return osg::Quat::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
double (&data(void))[4]
|
||||
{ return osg::Quat::_v; }
|
||||
|
||||
const osg::Quat& osg() const
|
||||
{ return *this; }
|
||||
osg::Quat& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
/// 3D Vector Class
|
||||
template<typename T>
|
||||
class SGQuat : protected SGQuatStorage<T> {
|
||||
class SGQuat {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
@@ -84,8 +55,6 @@ public:
|
||||
/// make sure it has at least 4 elements
|
||||
explicit SGQuat(const T* d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
explicit SGQuat(const osg::Quat& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
|
||||
/// Return a unit quaternion
|
||||
static SGQuat unit(void)
|
||||
@@ -158,48 +127,11 @@ public:
|
||||
static SGQuat fromLonLat(const SGGeod& geod)
|
||||
{ return fromLonLatRad(geod.getLongitudeRad(), geod.getLatitudeRad()); }
|
||||
|
||||
/// Return a quaternion rotation from the earth centered to the
|
||||
/// OpenGL/viewer horizontal local frame from given longitude and latitude.
|
||||
/// This frame matches the usual OpenGL axis directions. That is the target
|
||||
/// frame has an x-axis pointing eastwards, y-axis pointing up and y z-axis
|
||||
/// pointing south.
|
||||
static SGQuat viewHLRad(T lon, T lat)
|
||||
{
|
||||
// That bails down to a 3-2-1 euler sequence lon+pi/2, 0, -lat-pi
|
||||
// what is here is again the hand optimized version ...
|
||||
SGQuat q;
|
||||
T xd2 = -T(0.5)*lat - T(0.5)*SGMisc<T>::pi();
|
||||
T zd2 = T(0.5)*lon + T(0.25)*SGMisc<T>::pi();
|
||||
T Szd2 = sin(zd2);
|
||||
T Sxd2 = sin(xd2);
|
||||
T Czd2 = cos(zd2);
|
||||
T Cxd2 = cos(xd2);
|
||||
q.w() = Cxd2*Czd2;
|
||||
q.x() = Sxd2*Czd2;
|
||||
q.y() = Sxd2*Szd2;
|
||||
q.z() = Cxd2*Szd2;
|
||||
return q;
|
||||
}
|
||||
/// Like the above provided for convenience
|
||||
static SGQuat viewHLDeg(T lon, T lat)
|
||||
{ return viewHLRad(SGMisc<T>::deg2rad(lon), SGMisc<T>::deg2rad(lat)); }
|
||||
/// Like the above provided for convenience
|
||||
static SGQuat viewHL(const SGGeod& geod)
|
||||
{ return viewHLRad(geod.getLongitudeRad(), geod.getLatitudeRad()); }
|
||||
|
||||
/// Convert a quaternion rotation from the simulation frame
|
||||
/// to the view (OpenGL) frame. That is it just swaps the axis part of
|
||||
/// this current quaternion.
|
||||
/// That proves useful when you want to use the euler 3-2-1 sequence
|
||||
/// for the usual heading/pitch/roll sequence within the context of
|
||||
/// OpenGL/viewer frames.
|
||||
static SGQuat simToView(const SGQuat& q)
|
||||
{ return SGQuat(q.y(), -q.z(), -q.x(), q.w()); }
|
||||
|
||||
/// Create a quaternion from the angle axis representation
|
||||
static SGQuat fromAngleAxis(T angle, const SGVec3<T>& axis)
|
||||
{
|
||||
T angle2 = 0.5*angle;
|
||||
T angle2 = T(0.5)*angle;
|
||||
return fromRealImag(cos(angle2), T(sin(angle2))*axis);
|
||||
}
|
||||
|
||||
@@ -213,34 +145,36 @@ public:
|
||||
{
|
||||
T nAxis = norm(axis);
|
||||
if (nAxis <= SGLimits<T>::min())
|
||||
return SGQuat(1, 0, 0, 0);
|
||||
T angle2 = 0.5*nAxis;
|
||||
return SGQuat::unit();
|
||||
T angle2 = T(0.5)*nAxis;
|
||||
return fromRealImag(cos(angle2), T(sin(angle2)/nAxis)*axis);
|
||||
}
|
||||
|
||||
/// Return a quaternion that rotates the from vector onto the to vector.
|
||||
static SGQuat fromRotateTo(const SGVec3<T>& from, const SGVec3<T>& to)
|
||||
{
|
||||
T nfrom = norm(from);
|
||||
T nto = norm(to);
|
||||
if (nfrom < SGLimits<T>::min() || nto < SGLimits<T>::min())
|
||||
if (nfrom <= SGLimits<T>::min() || nto <= SGLimits<T>::min())
|
||||
return SGQuat::unit();
|
||||
|
||||
return SGQuat::fromRotateToNorm((1/nfrom)*from, (1/nto)*to);
|
||||
}
|
||||
|
||||
// FIXME more finegrained error behavour.
|
||||
/// Return a quaternion that rotates v1 onto the i1-th unit vector
|
||||
/// and v2 into a plane that is spanned by the i2-th and i1-th unit vector.
|
||||
static SGQuat fromRotateTo(const SGVec3<T>& v1, unsigned i1,
|
||||
const SGVec3<T>& v2, unsigned i2)
|
||||
{
|
||||
T nrmv1 = norm(v1);
|
||||
T nrmv2 = norm(v2);
|
||||
if (nrmv1 < SGLimits<T>::min() || nrmv2 < SGLimits<T>::min())
|
||||
if (nrmv1 <= SGLimits<T>::min() || nrmv2 <= SGLimits<T>::min())
|
||||
return SGQuat::unit();
|
||||
|
||||
SGVec3<T> nv1 = (1/nrmv1)*v1;
|
||||
SGVec3<T> nv2 = (1/nrmv2)*v2;
|
||||
T dv1v2 = dot(nv1, nv2);
|
||||
if (fabs(fabs(dv1v2)-1) < SGLimits<T>::epsilon())
|
||||
if (fabs(fabs(dv1v2)-1) <= SGLimits<T>::epsilon())
|
||||
return SGQuat::unit();
|
||||
|
||||
// The target vector for the first rotation
|
||||
@@ -261,12 +195,12 @@ public:
|
||||
|
||||
SGVec3<T> tnv2 = q.transform(nv2);
|
||||
T cosang = dot(nto2, tnv2);
|
||||
T cos05ang = T(0.5+0.5*cosang);
|
||||
T cos05ang = T(0.5)+T(0.5)*cosang;
|
||||
if (cos05ang <= 0)
|
||||
cosang = T(0);
|
||||
cosang = 0;
|
||||
cos05ang = sqrt(cos05ang);
|
||||
T sig = dot(nto1, cross(nto2, tnv2));
|
||||
T sin05ang = T(0.5-0.5*cosang);
|
||||
T sin05ang = T(0.5)-T(0.5)*cosang;
|
||||
if (sin05ang <= 0)
|
||||
sin05ang = 0;
|
||||
sin05ang = copysign(sqrt(sin05ang), sig);
|
||||
@@ -329,24 +263,24 @@ public:
|
||||
|
||||
T num = 2*(y()*z() + w()*x());
|
||||
T den = sqrQW - sqrQX - sqrQY + sqrQZ;
|
||||
if (fabs(den) < SGLimits<T>::min() &&
|
||||
fabs(num) < SGLimits<T>::min())
|
||||
if (fabs(den) <= SGLimits<T>::min() &&
|
||||
fabs(num) <= SGLimits<T>::min())
|
||||
xRad = 0;
|
||||
else
|
||||
xRad = atan2(num, den);
|
||||
|
||||
T tmp = 2*(x()*z() - w()*y());
|
||||
if (tmp < -1)
|
||||
yRad = 0.5*SGMisc<T>::pi();
|
||||
else if (1 < tmp)
|
||||
yRad = -0.5*SGMisc<T>::pi();
|
||||
if (tmp <= -1)
|
||||
yRad = T(0.5)*SGMisc<T>::pi();
|
||||
else if (1 <= tmp)
|
||||
yRad = -T(0.5)*SGMisc<T>::pi();
|
||||
else
|
||||
yRad = -asin(tmp);
|
||||
|
||||
num = 2*(x()*y() + w()*z());
|
||||
den = sqrQW + sqrQX - sqrQY - sqrQZ;
|
||||
if (fabs(den) < SGLimits<T>::min() &&
|
||||
fabs(num) < SGLimits<T>::min())
|
||||
if (fabs(den) <= SGLimits<T>::min() &&
|
||||
fabs(num) <= SGLimits<T>::min())
|
||||
zRad = 0;
|
||||
else {
|
||||
T psi = atan2(num, den);
|
||||
@@ -369,14 +303,14 @@ public:
|
||||
void getAngleAxis(T& angle, SGVec3<T>& axis) const
|
||||
{
|
||||
T nrm = norm(*this);
|
||||
if (nrm < SGLimits<T>::min()) {
|
||||
if (nrm <= SGLimits<T>::min()) {
|
||||
angle = 0;
|
||||
axis = SGVec3<T>(0, 0, 0);
|
||||
} else {
|
||||
T rNrm = 1/nrm;
|
||||
angle = acos(SGMisc<T>::max(-1, SGMisc<T>::min(1, rNrm*w())));
|
||||
T sAng = sin(angle);
|
||||
if (fabs(sAng) < SGLimits<T>::min())
|
||||
if (fabs(sAng) <= SGLimits<T>::min())
|
||||
axis = SGVec3<T>(1, 0, 0);
|
||||
else
|
||||
axis = (rNrm/sAng)*imag(*this);
|
||||
@@ -432,17 +366,11 @@ public:
|
||||
{ return data()[3]; }
|
||||
|
||||
/// Get the data pointer
|
||||
using SGQuatStorage<T>::data;
|
||||
|
||||
/// Readonly interface function to ssg's sgQuat/sgdQuat
|
||||
const T (&sg(void) const)[4]
|
||||
{ return data(); }
|
||||
/// Interface function to ssg's sgQuat/sgdQuat
|
||||
T (&sg(void))[4]
|
||||
{ return data(); }
|
||||
|
||||
/// Interface function to osg's Quat*
|
||||
using SGQuatStorage<T>::osg;
|
||||
const T (&data(void) const)[4]
|
||||
{ return _data; }
|
||||
/// Get the data pointer
|
||||
T (&data(void))[4]
|
||||
{ return _data; }
|
||||
|
||||
/// Inplace addition
|
||||
SGQuat& operator+=(const SGQuat& v)
|
||||
@@ -493,10 +421,10 @@ public:
|
||||
{
|
||||
SGQuat deriv;
|
||||
|
||||
deriv.w() = 0.5*(-x()*angVel(0) - y()*angVel(1) - z()*angVel(2));
|
||||
deriv.x() = 0.5*( w()*angVel(0) - z()*angVel(1) + y()*angVel(2));
|
||||
deriv.y() = 0.5*( z()*angVel(0) + w()*angVel(1) - x()*angVel(2));
|
||||
deriv.z() = 0.5*(-y()*angVel(0) + x()*angVel(1) + w()*angVel(2));
|
||||
deriv.w() = T(0.5)*(-x()*angVel(0) - y()*angVel(1) - z()*angVel(2));
|
||||
deriv.x() = T(0.5)*( w()*angVel(0) - z()*angVel(1) + y()*angVel(2));
|
||||
deriv.y() = T(0.5)*( z()*angVel(0) + w()*angVel(1) - x()*angVel(2));
|
||||
deriv.z() = T(0.5)*(-y()*angVel(0) + x()*angVel(1) + w()*angVel(2));
|
||||
|
||||
return deriv;
|
||||
}
|
||||
@@ -521,7 +449,7 @@ private:
|
||||
// in the interval [-pi,pi]. That means that 0.5*angle is in the interval
|
||||
// [-pi/2,pi/2]. But in that range the cosine is allways >= 0.
|
||||
// So we do not need to care for egative roots in the following equation:
|
||||
T cos05ang = sqrt(0.5+0.5*cosang);
|
||||
T cos05ang = sqrt(T(0.5)+T(0.5)*cosang);
|
||||
|
||||
|
||||
// Now our assumption of angles <= 90 deg comes in play.
|
||||
@@ -561,6 +489,8 @@ private:
|
||||
SGQuat q2 = SGQuat::fromRotateToSmaller90Deg(-cosang, -from, to);
|
||||
return q1*q2;
|
||||
}
|
||||
|
||||
T _data[4];
|
||||
};
|
||||
|
||||
/// Unary +, do nothing ...
|
||||
@@ -759,7 +689,7 @@ interpolate(T t, const SGQuat<T>& src, const SGQuat<T>& dst)
|
||||
// need the scales now, if the angle is very small, do linear interpolation
|
||||
// to avoid instabilities
|
||||
T scale0, scale1;
|
||||
if (fabs(o) < SGLimits<T>::epsilon()) {
|
||||
if (fabs(o) <= SGLimits<T>::epsilon()) {
|
||||
scale0 = 1 - t;
|
||||
scale1 = t;
|
||||
} else {
|
||||
@@ -790,4 +720,16 @@ SGQuatd
|
||||
toQuatd(const SGQuatf& v)
|
||||
{ return SGQuatd(v(0), v(1), v(2), v(3)); }
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
inline
|
||||
SGQuatd
|
||||
toSG(const osg::Quat& q)
|
||||
{ return SGQuatd(q[0], q[1], q[2], q[3]); }
|
||||
|
||||
inline
|
||||
osg::Quat
|
||||
toOsg(const SGQuatd& q)
|
||||
{ return osg::Quat(q[0], q[1], q[2], q[3]); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,6 +26,10 @@ public:
|
||||
SGRay(const SGVec3<T>& origin, const SGVec3<T>& dir) :
|
||||
_origin(origin), _direction(dir)
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGRay(const SGRay<S>& ray) :
|
||||
_origin(ray.getOrigin()), _direction(ray.getDirection())
|
||||
{ }
|
||||
|
||||
void set(const SGVec3<T>& origin, const SGVec3<T>& dir)
|
||||
{ _origin = origin; _direction = dir; }
|
||||
|
||||
@@ -28,6 +28,11 @@ public:
|
||||
_center(center),
|
||||
_radius(radius)
|
||||
{ }
|
||||
template<typename S>
|
||||
explicit SGSphere(const SGSphere<S>& sphere) :
|
||||
_center(sphere.getCenter()),
|
||||
_radius(sphere.getRadius())
|
||||
{ }
|
||||
|
||||
const SGVec3<T>& getCenter() const
|
||||
{ return _center; }
|
||||
@@ -41,7 +46,7 @@ public:
|
||||
T getRadius2() const
|
||||
{ return _radius*_radius; }
|
||||
|
||||
const bool empty() const
|
||||
bool empty() const
|
||||
{ return !valid(); }
|
||||
|
||||
bool valid() const
|
||||
@@ -68,6 +73,65 @@ public:
|
||||
_radius = newRadius;
|
||||
}
|
||||
|
||||
void expandBy(const SGSphere<T>& s)
|
||||
{
|
||||
if (s.empty())
|
||||
return;
|
||||
|
||||
if (empty()) {
|
||||
_center = s.getCenter();
|
||||
_radius = s.getRadius();
|
||||
return;
|
||||
}
|
||||
|
||||
T dist = length(_center - s.getCenter());
|
||||
if (dist <= SGLimits<T>::min()) {
|
||||
_radius = SGMisc<T>::max(_radius, s._radius);
|
||||
return;
|
||||
}
|
||||
|
||||
// already included
|
||||
if (dist + s.getRadius() <= _radius)
|
||||
return;
|
||||
|
||||
// new one includes all
|
||||
if (dist + _radius <= s.getRadius()) {
|
||||
_center = s.getCenter();
|
||||
_radius = s.getRadius();
|
||||
return;
|
||||
}
|
||||
|
||||
T newRadius = T(0.5)*(_radius + dist + s.getRadius());
|
||||
T ratio = (newRadius - _radius) / dist;
|
||||
_radius = newRadius;
|
||||
|
||||
_center[0] += ratio*(s._center[0] - _center[0]);
|
||||
_center[1] += ratio*(s._center[1] - _center[1]);
|
||||
_center[2] += ratio*(s._center[2] - _center[2]);
|
||||
}
|
||||
|
||||
void expandBy(const SGBox<T>& box)
|
||||
{
|
||||
if (box.empty())
|
||||
return;
|
||||
|
||||
if (empty()) {
|
||||
_center = box.getCenter();
|
||||
_radius = T(0.5)*length(box.getSize());
|
||||
return;
|
||||
}
|
||||
|
||||
SGVec3<T> boxCenter = box.getCenter();
|
||||
SGVec3<T> corner;
|
||||
for (unsigned i = 0; i < 3; ++i) {
|
||||
if (_center[i] < boxCenter[i])
|
||||
corner[i] = box.getMax()[i];
|
||||
else
|
||||
corner[i] = box.getMin()[i];
|
||||
}
|
||||
expandBy(corner);
|
||||
}
|
||||
|
||||
private:
|
||||
SGVec3<T> _center;
|
||||
T _radius;
|
||||
|
||||
@@ -41,14 +41,8 @@ public:
|
||||
_d[1] = v[2] - v[0];
|
||||
}
|
||||
|
||||
SGVec3d getCenter() const
|
||||
{
|
||||
SGBoxd box;
|
||||
box.expandBy(_v0);
|
||||
box.expandBy(_v0 + _d[0]);
|
||||
box.expandBy(_v0 + _d[1]);
|
||||
return box.getCenter();
|
||||
}
|
||||
SGVec3<T> getCenter() const
|
||||
{ return _v0 + T(1)/T(3)*(_d[0] + _d[1]); }
|
||||
|
||||
// note that the index is unchecked
|
||||
SGVec3<T> getVertex(unsigned i) const
|
||||
@@ -77,6 +71,16 @@ public:
|
||||
_d[0] = _d[1];
|
||||
_d[1] = tmp;
|
||||
}
|
||||
|
||||
SGTriangle<T> transform(const SGMatrix<T>& matrix) const
|
||||
{
|
||||
SGTriangle<T> triangle;
|
||||
triangle._v0 = matrix.xformPt(_v0);
|
||||
triangle._d[0] = matrix.xformVec(_d[0]);
|
||||
triangle._d[1] = matrix.xformVec(_d[1]);
|
||||
return triangle;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Store one vertex directly, _d is the offset of the other two
|
||||
/// vertices wrt the base vertex
|
||||
|
||||
+56
-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
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -22,58 +22,14 @@
|
||||
#include <ieeefp.h>
|
||||
#endif
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Vec2f>
|
||||
#include <osg/Vec2d>
|
||||
|
||||
template<typename T>
|
||||
struct SGVec2Storage {
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[2]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[2]
|
||||
{ return _data; }
|
||||
|
||||
void osg() const
|
||||
{ }
|
||||
|
||||
private:
|
||||
T _data[2];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec2Storage<float> : public osg::Vec2f {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const float (&data(void) const)[2]
|
||||
{ return osg::Vec2f::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
float (&data(void))[2]
|
||||
{ return osg::Vec2f::_v; }
|
||||
|
||||
const osg::Vec2f& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec2f& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec2Storage<double> : public osg::Vec2d {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const double (&data(void) const)[2]
|
||||
{ return osg::Vec2d::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
double (&data(void))[2]
|
||||
{ return osg::Vec2d::_v; }
|
||||
|
||||
const osg::Vec2d& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec2d& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
/// 2D Vector Class
|
||||
template<typename T>
|
||||
class SGVec2 : protected SGVec2Storage<T> {
|
||||
class SGVec2 {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
@@ -96,9 +52,8 @@ public:
|
||||
/// make sure it has at least 2 elements
|
||||
explicit SGVec2(const T* d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; }
|
||||
explicit SGVec2(const osg::Vec2f& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; }
|
||||
explicit SGVec2(const osg::Vec2d& d)
|
||||
template<typename S>
|
||||
explicit SGVec2(const SGVec2<S>& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; }
|
||||
|
||||
/// Access by index, the index is unchecked
|
||||
@@ -128,18 +83,12 @@ public:
|
||||
T& y(void)
|
||||
{ return data()[1]; }
|
||||
|
||||
/// Get the data pointer
|
||||
using SGVec2Storage<T>::data;
|
||||
|
||||
/// Readonly interface function to ssg's sgVec2/sgdVec2
|
||||
const T (&sg(void) const)[2]
|
||||
{ return data(); }
|
||||
/// Interface function to ssg's sgVec2/sgdVec2
|
||||
T (&sg(void))[2]
|
||||
{ return data(); }
|
||||
|
||||
/// Interface function to osg's Vec2*
|
||||
using SGVec2Storage<T>::osg;
|
||||
/// Access raw data
|
||||
const T (&data(void) const)[2]
|
||||
{ return _data; }
|
||||
/// Access raw data
|
||||
T (&data(void))[2]
|
||||
{ return _data; }
|
||||
|
||||
/// Inplace addition
|
||||
SGVec2& operator+=(const SGVec2& v)
|
||||
@@ -164,6 +113,9 @@ public:
|
||||
{ return SGVec2(1, 0); }
|
||||
static SGVec2 e2(void)
|
||||
{ return SGVec2(0, 1); }
|
||||
|
||||
private:
|
||||
T _data[2];
|
||||
};
|
||||
|
||||
/// Unary +, do nothing ...
|
||||
@@ -292,7 +244,12 @@ template<typename T>
|
||||
inline
|
||||
SGVec2<T>
|
||||
normalize(const SGVec2<T>& v)
|
||||
{ return (1/norm(v))*v; }
|
||||
{
|
||||
T normv = norm(v);
|
||||
if (normv <= SGLimits<T>::min())
|
||||
return SGVec2<T>::zeros();
|
||||
return (1/normv)*v;
|
||||
}
|
||||
|
||||
/// Return true if exactly the same
|
||||
template<typename T>
|
||||
@@ -379,6 +336,18 @@ T
|
||||
distSqr(const SGVec2<T>& v1, const SGVec2<T>& v2)
|
||||
{ SGVec2<T> tmp = v1 - v2; return dot(tmp, tmp); }
|
||||
|
||||
// calculate the projection of u along the direction of d.
|
||||
template<typename T>
|
||||
inline
|
||||
SGVec2<T>
|
||||
projection(const SGVec2<T>& u, const SGVec2<T>& d)
|
||||
{
|
||||
T denom = dot(d, d);
|
||||
T ud = dot(u, d);
|
||||
if (SGLimits<T>::min() < denom) return u;
|
||||
else return d * (dot(u, d) / denom);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<typename T>
|
||||
inline
|
||||
@@ -406,4 +375,27 @@ SGVec2d
|
||||
toVec2d(const SGVec2f& v)
|
||||
{ return SGVec2d(v(0), v(1)); }
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
inline
|
||||
SGVec2d
|
||||
toSG(const osg::Vec2d& v)
|
||||
{ return SGVec2d(v[0], v[1]); }
|
||||
|
||||
inline
|
||||
SGVec2f
|
||||
toSG(const osg::Vec2f& v)
|
||||
{ return SGVec2f(v[0], v[1]); }
|
||||
|
||||
inline
|
||||
osg::Vec2d
|
||||
toOsg(const SGVec2d& v)
|
||||
{ return osg::Vec2d(v[0], v[1]); }
|
||||
|
||||
inline
|
||||
osg::Vec2f
|
||||
toOsg(const SGVec2f& v)
|
||||
{ return osg::Vec2f(v[0], v[1]); }
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+57
-65
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
// Copyright (C) 2006-2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -18,58 +18,14 @@
|
||||
#ifndef SGVec3_H
|
||||
#define SGVec3_H
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/Vec3d>
|
||||
|
||||
template<typename T>
|
||||
struct SGVec3Storage {
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[3]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[3]
|
||||
{ return _data; }
|
||||
|
||||
void osg() const
|
||||
{ }
|
||||
|
||||
private:
|
||||
T _data[3];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec3Storage<float> : public osg::Vec3f {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const float (&data(void) const)[3]
|
||||
{ return osg::Vec3f::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
float (&data(void))[3]
|
||||
{ return osg::Vec3f::_v; }
|
||||
|
||||
const osg::Vec3f& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec3f& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec3Storage<double> : public osg::Vec3d {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const double (&data(void) const)[3]
|
||||
{ return osg::Vec3d::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
double (&data(void))[3]
|
||||
{ return osg::Vec3d::_v; }
|
||||
|
||||
const osg::Vec3d& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec3d& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
/// 3D Vector Class
|
||||
template<typename T>
|
||||
class SGVec3 : protected SGVec3Storage<T> {
|
||||
class SGVec3 {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
@@ -92,9 +48,8 @@ public:
|
||||
/// make sure it has at least 3 elements
|
||||
explicit SGVec3(const T* d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
||||
explicit SGVec3(const osg::Vec3f& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
||||
explicit SGVec3(const osg::Vec3d& d)
|
||||
template<typename S>
|
||||
explicit SGVec3(const SGVec3<S>& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; }
|
||||
explicit SGVec3(const SGVec2<T>& v2, const T& v3 = 0)
|
||||
{ data()[0] = v2[0]; data()[1] = v2[1]; data()[2] = v3; }
|
||||
@@ -132,18 +87,12 @@ public:
|
||||
T& z(void)
|
||||
{ return data()[2]; }
|
||||
|
||||
/// Get the data pointer
|
||||
using SGVec3Storage<T>::data;
|
||||
|
||||
/// Readonly interface function to ssg's sgVec3/sgdVec3
|
||||
const T (&sg(void) const)[3]
|
||||
{ return data(); }
|
||||
/// Interface function to ssg's sgVec3/sgdVec3
|
||||
T (&sg(void))[3]
|
||||
{ return data(); }
|
||||
|
||||
/// Interface function to osg's Vec3*
|
||||
using SGVec3Storage<T>::osg;
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[3]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[3]
|
||||
{ return _data; }
|
||||
|
||||
/// Inplace addition
|
||||
SGVec3& operator+=(const SGVec3& v)
|
||||
@@ -177,6 +126,9 @@ public:
|
||||
/// Constructor. Initialize by a geocentric coordinate
|
||||
/// Note that this conversion is relatively expensive to compute
|
||||
static SGVec3 fromGeoc(const SGGeoc& geoc);
|
||||
|
||||
private:
|
||||
T _data[3];
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -400,12 +352,18 @@ perpendicular(const SGVec3<T>& v)
|
||||
}
|
||||
}
|
||||
|
||||
/// The euclidean norm of the vector, that is what most people call length
|
||||
/// Construct a unit vector in the given direction.
|
||||
/// or the zero vector if the input vector is zero.
|
||||
template<typename T>
|
||||
inline
|
||||
SGVec3<T>
|
||||
normalize(const SGVec3<T>& v)
|
||||
{ return (1/norm(v))*v; }
|
||||
{
|
||||
T normv = norm(v);
|
||||
if (normv <= SGLimits<T>::min())
|
||||
return SGVec3<T>::zeros();
|
||||
return (1/normv)*v;
|
||||
}
|
||||
|
||||
/// Return true if exactly the same
|
||||
template<typename T>
|
||||
@@ -496,6 +454,18 @@ T
|
||||
distSqr(const SGVec3<T>& v1, const SGVec3<T>& v2)
|
||||
{ SGVec3<T> tmp = v1 - v2; return dot(tmp, tmp); }
|
||||
|
||||
// calculate the projection of u along the direction of d.
|
||||
template<typename T>
|
||||
inline
|
||||
SGVec3<T>
|
||||
projection(const SGVec3<T>& u, const SGVec3<T>& d)
|
||||
{
|
||||
T denom = dot(d, d);
|
||||
T ud = dot(u, d);
|
||||
if (SGLimits<T>::min() < denom) return u;
|
||||
else return d * (dot(u, d) / denom);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<typename T>
|
||||
inline
|
||||
@@ -524,4 +494,26 @@ SGVec3d
|
||||
toVec3d(const SGVec3f& v)
|
||||
{ return SGVec3d(v(0), v(1), v(2)); }
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
inline
|
||||
SGVec3d
|
||||
toSG(const osg::Vec3d& v)
|
||||
{ return SGVec3d(v[0], v[1], v[2]); }
|
||||
|
||||
inline
|
||||
SGVec3f
|
||||
toSG(const osg::Vec3f& v)
|
||||
{ return SGVec3f(v[0], v[1], v[2]); }
|
||||
|
||||
inline
|
||||
osg::Vec3d
|
||||
toOsg(const SGVec3d& v)
|
||||
{ return osg::Vec3d(v[0], v[1], v[2]); }
|
||||
|
||||
inline
|
||||
osg::Vec3f
|
||||
toOsg(const SGVec3f& v)
|
||||
{ return osg::Vec3f(v[0], v[1], v[2]); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+55
-65
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
// Copyright (C) 2006-2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
@@ -18,58 +18,14 @@
|
||||
#ifndef SGVec4_H
|
||||
#define SGVec4_H
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
#include <osg/Vec4f>
|
||||
#include <osg/Vec4d>
|
||||
|
||||
template<typename T>
|
||||
struct SGVec4Storage {
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[4]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[4]
|
||||
{ return _data; }
|
||||
|
||||
void osg() const
|
||||
{ }
|
||||
|
||||
private:
|
||||
T _data[4];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec4Storage<float> : public osg::Vec4f {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const float (&data(void) const)[4]
|
||||
{ return osg::Vec4f::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
float (&data(void))[4]
|
||||
{ return osg::Vec4f::_v; }
|
||||
|
||||
const osg::Vec4f& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec4f& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct SGVec4Storage<double> : public osg::Vec4d {
|
||||
/// Access raw data by index, the index is unchecked
|
||||
const double (&data(void) const)[4]
|
||||
{ return osg::Vec4d::_v; }
|
||||
/// Access raw data by index, the index is unchecked
|
||||
double (&data(void))[4]
|
||||
{ return osg::Vec4d::_v; }
|
||||
|
||||
const osg::Vec4d& osg() const
|
||||
{ return *this; }
|
||||
osg::Vec4d& osg()
|
||||
{ return *this; }
|
||||
};
|
||||
#endif
|
||||
|
||||
/// 4D Vector Class
|
||||
template<typename T>
|
||||
class SGVec4 : protected SGVec4Storage<T> {
|
||||
class SGVec4 {
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
@@ -92,14 +48,12 @@ public:
|
||||
/// make sure it has at least 3 elements
|
||||
explicit SGVec4(const T* d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
explicit SGVec4(const osg::Vec4f& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
explicit SGVec4(const osg::Vec4d& d)
|
||||
template<typename S>
|
||||
explicit SGVec4(const SGVec4<S>& d)
|
||||
{ data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; }
|
||||
explicit SGVec4(const SGVec3<T>& v3, const T& v4 = 0)
|
||||
{ data()[0] = v3[0]; data()[1] = v3[1]; data()[2] = v3[2]; data()[3] = v4; }
|
||||
|
||||
|
||||
/// Access by index, the index is unchecked
|
||||
const T& operator()(unsigned i) const
|
||||
{ return data()[i]; }
|
||||
@@ -139,18 +93,12 @@ public:
|
||||
T& w(void)
|
||||
{ return data()[3]; }
|
||||
|
||||
/// Get the data pointer
|
||||
using SGVec4Storage<T>::data;
|
||||
|
||||
/// Readonly interface function to ssg's sgVec4/sgdVec4
|
||||
const T (&sg(void) const)[4]
|
||||
{ return data(); }
|
||||
/// Interface function to ssg's sgVec4/sgdVec4
|
||||
T (&sg(void))[4]
|
||||
{ return data(); }
|
||||
|
||||
/// Interface function to osg's Vec4*
|
||||
using SGVec4Storage<T>::osg;
|
||||
/// Readonly raw storage interface
|
||||
const T (&data(void) const)[4]
|
||||
{ return _data; }
|
||||
/// Readonly raw storage interface
|
||||
T (&data(void))[4]
|
||||
{ return _data; }
|
||||
|
||||
/// Inplace addition
|
||||
SGVec4& operator+=(const SGVec4& v)
|
||||
@@ -179,6 +127,9 @@ public:
|
||||
{ return SGVec4(0, 0, 1, 0); }
|
||||
static SGVec4 e4(void)
|
||||
{ return SGVec4(0, 0, 0, 1); }
|
||||
|
||||
private:
|
||||
T _data[4];
|
||||
};
|
||||
|
||||
/// Unary +, do nothing ...
|
||||
@@ -337,7 +288,12 @@ template<typename T>
|
||||
inline
|
||||
SGVec4<T>
|
||||
normalize(const SGVec4<T>& v)
|
||||
{ return (1/norm(v))*v; }
|
||||
{
|
||||
T normv = norm(v);
|
||||
if (normv <= SGLimits<T>::min())
|
||||
return SGVec4<T>::zeros();
|
||||
return (1/normv)*v;
|
||||
}
|
||||
|
||||
/// Return true if exactly the same
|
||||
template<typename T>
|
||||
@@ -432,6 +388,18 @@ T
|
||||
distSqr(const SGVec4<T>& v1, const SGVec4<T>& v2)
|
||||
{ SGVec4<T> tmp = v1 - v2; return dot(tmp, tmp); }
|
||||
|
||||
// calculate the projection of u along the direction of d.
|
||||
template<typename T>
|
||||
inline
|
||||
SGVec4<T>
|
||||
projection(const SGVec4<T>& u, const SGVec4<T>& d)
|
||||
{
|
||||
T denom = dot(d, d);
|
||||
T ud = dot(u, d);
|
||||
if (SGLimits<T>::min() < denom) return u;
|
||||
else return d * (dot(u, d) / denom);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
template<typename T>
|
||||
inline
|
||||
@@ -460,4 +428,26 @@ SGVec4d
|
||||
toVec4d(const SGVec4f& v)
|
||||
{ return SGVec4d(v(0), v(1), v(2), v(3)); }
|
||||
|
||||
#ifndef NO_OPENSCENEGRAPH_INTERFACE
|
||||
inline
|
||||
SGVec4d
|
||||
toSG(const osg::Vec4d& v)
|
||||
{ return SGVec4d(v[0], v[1], v[2], v[3]); }
|
||||
|
||||
inline
|
||||
SGVec4f
|
||||
toSG(const osg::Vec4f& v)
|
||||
{ return SGVec4f(v[0], v[1], v[2], v[3]); }
|
||||
|
||||
inline
|
||||
osg::Vec4d
|
||||
toOsg(const SGVec4d& v)
|
||||
{ return osg::Vec4d(v[0], v[1], v[2], v[3]); }
|
||||
|
||||
inline
|
||||
osg::Vec4f
|
||||
toOsg(const SGVec4f& v)
|
||||
{ return osg::Vec4f(v[0], v[1], v[2], v[3]); }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Executable
+105
@@ -0,0 +1,105 @@
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2009 Frederic Bouvier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SIMGEAR_BEZIERCURVE_HXX
|
||||
#define SIMGEAR_BEZIERCURVE_HXX 1
|
||||
|
||||
#include <list>
|
||||
using std::list;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
template<class T>
|
||||
class BezierCurve {
|
||||
public:
|
||||
typedef list<T> PointList;
|
||||
|
||||
BezierCurve() : mMaxSubdiv( 3 ) {}
|
||||
BezierCurve( size_t aMaxSubdiv )
|
||||
: mMaxSubdiv( aMaxSubdiv ) {}
|
||||
BezierCurve( const T &p1, const T &p2, const T &p3, size_t aMaxSubdiv = 3 )
|
||||
: mMaxSubdiv( aMaxSubdiv ) {
|
||||
subdivide( p1, p2, p3 );
|
||||
}
|
||||
BezierCurve( const T &p1, const T &p2, const T &p3, const T &p4, size_t aMaxSubdiv = 3 )
|
||||
: mMaxSubdiv( aMaxSubdiv ) {
|
||||
subdivide( p1, p2, p3, p4 );
|
||||
}
|
||||
|
||||
void subdivide( const T &p1, const T &p2, const T &p3 ) {
|
||||
mPointList.clear();
|
||||
mPointList.push_back( p1 );
|
||||
recursiveSubdivide( p1, p2, p3, 1 );
|
||||
mPointList.push_back( p3 );
|
||||
}
|
||||
|
||||
void subdivide( const T &p1, const T &p2, const T &p3, const T &p4 ) {
|
||||
mPointList.clear();
|
||||
mPointList.push_back( p1 );
|
||||
recursiveSubdivide( p1, p2, p3, p4, 1 );
|
||||
mPointList.push_back( p4 );
|
||||
}
|
||||
|
||||
void setMaxSubdiv( size_t aMaxSubdiv ) { mMaxSubdiv = aMaxSubdiv; }
|
||||
void getMaxSubdiv() const { return mMaxSubdiv; }
|
||||
PointList &pointList() { return mPointList; }
|
||||
const PointList &pointList() const { return mPointList; }
|
||||
|
||||
private:
|
||||
T midPoint( const T &p1, const T &p2 ) {
|
||||
return ( p1 + p2 ) / 2;
|
||||
}
|
||||
bool recursiveSubdivide( const T &p1, const T &p2, const T &p3, size_t l ) {
|
||||
if ( l > mMaxSubdiv )
|
||||
return false;
|
||||
|
||||
T p12 = midPoint( p1, p2 ),
|
||||
p23 = midPoint( p2, p3 ),
|
||||
p123 = midPoint( p12, p23 );
|
||||
recursiveSubdivide( p1, p12, p123, l + 1 );
|
||||
mPointList.push_back( p123 );
|
||||
recursiveSubdivide( p123, p23, p3, l + 1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool recursiveSubdivide( const T &p1, const T &p2, const T &p3, const T &p4, size_t l ) {
|
||||
if ( l > mMaxSubdiv )
|
||||
return false;
|
||||
|
||||
T p12 = midPoint( p1, p2 ),
|
||||
p23 = midPoint( p2, p3 ),
|
||||
p34 = midPoint( p3, p4 ),
|
||||
p123 = midPoint( p12, p23 ),
|
||||
p234 = midPoint( p23, p34 ),
|
||||
p1234 = midPoint( p123, p234 );
|
||||
recursiveSubdivide( p1, p12, p123, p1234, l + 1 );
|
||||
mPointList.push_back( p1234 );
|
||||
recursiveSubdivide( p1234, p234, p34, p4, l + 1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
PointList mPointList;
|
||||
size_t mMaxSubdiv;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,9 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
@@ -33,6 +36,8 @@
|
||||
|
||||
#include "interpolater.hxx"
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
using std::string;
|
||||
|
||||
// Constructor -- starts with an empty table.
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include "simgear/structure/SGReferenced.hxx"
|
||||
#include <simgear/structure/SGReferenced.hxx>
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
class Point3D;
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
+18
-16
@@ -29,6 +29,20 @@
|
||||
#include "vector.hxx"
|
||||
|
||||
|
||||
// calculate the projection, p, of u along the direction of d.
|
||||
void sgProjection(sgVec3 p, const sgVec3 u, const sgVec3 d){
|
||||
double denom = sgScalarProductVec3(d,d);
|
||||
if (denom == 0.) sgCopyVec3(p, u);
|
||||
else sgScaleVec3(p, d, sgScalarProductVec3(u,d) / denom);
|
||||
}
|
||||
|
||||
// Same thing, except using double precision
|
||||
void sgProjection(sgdVec3 p, const sgdVec3 u, const sgdVec3 d){
|
||||
double denom = sgdScalarProductVec3(d,d);
|
||||
if (denom == 0.) sgdCopyVec3(p, u);
|
||||
else sgdScaleVec3(p, d, sgdScalarProductVec3(u,d) / denom);
|
||||
}
|
||||
|
||||
// Given a point p, and a line through p0 with direction vector d,
|
||||
// find the closest point (p1) on the line
|
||||
void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0,
|
||||
@@ -40,8 +54,7 @@ void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0,
|
||||
sgSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) );
|
||||
sgProjection(u1, u, d);
|
||||
|
||||
// calculate the point p1 along the line that is closest to p
|
||||
// p0 = p1 + u1
|
||||
@@ -60,12 +73,7 @@ void sgdClosestPointToLine( sgdVec3 p1, const sgdVec3 p, const sgdVec3 p0,
|
||||
sgdSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
double ud = sgdScalarProductVec3(u, d);
|
||||
double dd = sgdScalarProductVec3(d, d);
|
||||
double tmp = ud / dd;
|
||||
|
||||
sgdScaleVec3(u1, d, tmp);;
|
||||
sgProjection(u1, u, d);
|
||||
|
||||
// calculate the point p1 along the line that is closest to p
|
||||
// p0 = p1 + u1
|
||||
@@ -84,8 +92,7 @@ double sgClosestPointToLineDistSquared( const sgVec3 p, const sgVec3 p0,
|
||||
sgSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) );
|
||||
sgProjection(u1, u, d);
|
||||
|
||||
// v = u - u1 = vector from closest point on line, p1, to the
|
||||
// original point, p.
|
||||
@@ -106,12 +113,7 @@ double sgdClosestPointToLineDistSquared( const sgdVec3 p, const sgdVec3 p0,
|
||||
sgdSubVec3(u, p, p0);
|
||||
|
||||
// calculate the projection, u1, of u along d.
|
||||
// u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d;
|
||||
double ud = sgdScalarProductVec3(u, d);
|
||||
double dd = sgdScalarProductVec3(d, d);
|
||||
double tmp = ud / dd;
|
||||
|
||||
sgdScaleVec3(u1, d, tmp);;
|
||||
sgProjection(u1, u, d);
|
||||
|
||||
// v = u - u1 = vector from closest point on line, p1, to the
|
||||
// original point, p.
|
||||
|
||||
+11
-1
@@ -38,7 +38,17 @@
|
||||
|
||||
|
||||
/**
|
||||
* Map a vector onto a plane.
|
||||
* calculate the projection, p, of u along the direction of d.
|
||||
* @param p (out) the projection
|
||||
* @param u (in) the vector to be projected
|
||||
* @param d (in) the direction onto which we project
|
||||
*/
|
||||
void sgProjection(sgVec3 p, const sgVec3 u, const sgVec3 d);
|
||||
void sgProjection(sgdVec3 p, const sgdVec3 u, const sgdVec3 d);
|
||||
|
||||
|
||||
/**
|
||||
* Map i.e. project a vector onto a plane.
|
||||
* @param normal (in) normal vector for the plane
|
||||
* @param v0 (in) a point on the plane
|
||||
* @param vec (in) the vector to map onto the plane
|
||||
|
||||
@@ -24,13 +24,13 @@ libsgmisc_a_SOURCES = \
|
||||
interpolator.cxx \
|
||||
PathOptions.cxx
|
||||
|
||||
noinst_PROGRAMS = tabbed_value_test swap_test
|
||||
#noinst_PROGRAMS = tabbed_value_test swap_test
|
||||
|
||||
tabbed_value_test_SOURCES = tabbed_values_test.cxx
|
||||
tabbed_value_test_LDADD = \
|
||||
libsgmisc.a \
|
||||
$(top_builddir)/simgear/xml/libsgxml.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a
|
||||
#tabbed_value_test_SOURCES = tabbed_values_test.cxx
|
||||
#tabbed_value_test_LDADD = \
|
||||
# libsgmisc.a \
|
||||
# $(top_builddir)/simgear/xml/libsgxml.a \
|
||||
# $(top_builddir)/simgear/debug/libsgdebug.a
|
||||
|
||||
$(top_builddir)/simgear/xml/libsgxml.a:
|
||||
cd $(top_builddir)/simgear/xml && $(MAKE) $(AM_MAKEFLAGS) libsgxml.a
|
||||
@@ -38,6 +38,6 @@ $(top_builddir)/simgear/xml/libsgxml.a:
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a:
|
||||
cd $(top_builddir)/simgear/debug && $(MAKE) $(AM_MAKEFLAGS) libsgdebug.a
|
||||
|
||||
swap_test_SOURCES = swap_test.cpp
|
||||
#swap_test_SOURCES = swap_test.cpp
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include "interpolator.hxx"
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
void SGInterpolator::addNew(SGPropertyNode* prop, int nPoints)
|
||||
{
|
||||
// Set the property type to a double, if it isn't already, and
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
#include "strutils.hxx"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace simgear {
|
||||
namespace strutils {
|
||||
|
||||
|
||||
@@ -30,16 +30,12 @@
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <vector>
|
||||
using std::vector;
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace simgear {
|
||||
namespace strutils {
|
||||
namespace strutils {
|
||||
|
||||
// /**
|
||||
// * atof() wrapper for "string" type
|
||||
@@ -64,9 +60,9 @@ namespace simgear {
|
||||
* @param s String to strip.
|
||||
* @return The stripped string.
|
||||
*/
|
||||
string lstrip( const string& s );
|
||||
string rstrip( const string& s );
|
||||
string strip( const string& s );
|
||||
std::string lstrip( const std::string& s );
|
||||
std::string rstrip( const std::string& s );
|
||||
std::string strip( const std::string& s );
|
||||
|
||||
/**
|
||||
* Split a string into a words using 'sep' as the delimiter string.
|
||||
@@ -79,12 +75,12 @@ namespace simgear {
|
||||
* resulting in at most maxsplit+1 words.
|
||||
* @return Array of words.
|
||||
*/
|
||||
vector<string>
|
||||
split( const string& s,
|
||||
std::vector<std::string>
|
||||
split( const std::string& s,
|
||||
const char* sep = 0,
|
||||
int maxsplit = 0 );
|
||||
|
||||
} // end namespace strutils
|
||||
|
||||
} // end namespace strutils
|
||||
} // end namespace simgear
|
||||
|
||||
#endif // STRUTILS_H
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
// $Id$
|
||||
|
||||
#include <cstdlib>
|
||||
#include <assert.h>
|
||||
|
||||
#include "tabbed_values.hxx"
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
SGTabbedValues::SGTabbedValues(const char *line) :
|
||||
_line(line)
|
||||
|
||||
@@ -149,6 +149,7 @@ enter this in the official comments in case I forget again. :-)
|
||||
|
||||
#include "texcoord.hxx"
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
// using std::cout;
|
||||
// using std::endl;
|
||||
|
||||
|
||||
+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));
|
||||
}
|
||||
|
||||
static naRef f_flush(naContext c, naRef me, int argc, naRef* args)
|
||||
{
|
||||
struct naIOGhost* g = argc==1 ? ioghost(args[0]) : 0;
|
||||
if(!g)
|
||||
naRuntimeError(c, "bad argument to flush()");
|
||||
g->type->flush(c, g->handle);
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static void ghostDestroy(void* g)
|
||||
{
|
||||
struct naIOGhost* io = (struct naIOGhost*)g;
|
||||
@@ -111,6 +120,11 @@ static int iotell(naContext c, void* f)
|
||||
return n;
|
||||
}
|
||||
|
||||
static void ioflush(naContext c, void* f)
|
||||
{
|
||||
if(fflush(f)) naRuntimeError(c, strerror(errno));
|
||||
}
|
||||
|
||||
static void iodestroy(void* f)
|
||||
{
|
||||
if(f != stdin && f != stdout && f != stderr)
|
||||
@@ -118,7 +132,7 @@ static void iodestroy(void* f)
|
||||
}
|
||||
|
||||
struct naIOType naStdIOType = { ioclose, ioread, iowrite, ioseek,
|
||||
iotell, iodestroy };
|
||||
iotell, ioflush, iodestroy };
|
||||
|
||||
naRef naIOGhost(naContext c, FILE* f)
|
||||
{
|
||||
@@ -181,6 +195,26 @@ static naRef f_readln(naContext ctx, naRef me, int argc, naRef* args)
|
||||
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)
|
||||
{
|
||||
int n=0;
|
||||
@@ -192,11 +226,12 @@ static naRef f_stat(naContext ctx, naRef me, int argc, naRef* args)
|
||||
naRuntimeError(ctx, strerror(errno));
|
||||
}
|
||||
result = naNewVector(ctx);
|
||||
naVec_setsize(result, 11);
|
||||
naVec_setsize(result, 12);
|
||||
#define FLD(x) naVec_set(result, n++, naNum(s.st_##x));
|
||||
FLD(dev); FLD(ino); FLD(mode); FLD(nlink); FLD(uid); FLD(gid);
|
||||
FLD(rdev); FLD(size); FLD(atime); FLD(mtime); FLD(ctime);
|
||||
#undef FLD
|
||||
naVec_set(result, n++, ftype(ctx, s.st_mode));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -206,6 +241,7 @@ static naCFuncItem funcs[] = {
|
||||
{ "write", f_write },
|
||||
{ "seek", f_seek },
|
||||
{ "tell", f_tell },
|
||||
{ "flush", f_flush },
|
||||
{ "open", f_open },
|
||||
{ "readln", f_readln },
|
||||
{ "stat", f_stat },
|
||||
|
||||
@@ -15,6 +15,7 @@ struct naIOType {
|
||||
int (*write)(naContext c, void* f, char* buf, unsigned int len);
|
||||
void (*seek) (naContext c, void* f, unsigned int off, int whence);
|
||||
int (*tell) (naContext c, void* f);
|
||||
void (*flush) (naContext c, void* f);
|
||||
void (*destroy)(void* f);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
* tested */
|
||||
# define NASAL_NAN64
|
||||
#elif defined(_M_IX86) || defined(i386) || defined(__x86_64) || \
|
||||
defined(__ia64__) || defined(_M_IA64) || defined(__ARMEL__)
|
||||
defined(__ia64__) || defined(_M_IA64) || defined(__ARMEL__) || \
|
||||
defined(_M_X64)
|
||||
# define NASAL_LE
|
||||
#elif defined(__sparc) || defined(__ppc__) || defined(__PPC) || \
|
||||
defined(__mips) || defined(__ARMEB__)
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include "AtomicChangeListener.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
MultiChangeListener::MultiChangeListener()
|
||||
{
|
||||
}
|
||||
|
||||
void MultiChangeListener::valueChanged(SGPropertyNode* node)
|
||||
{
|
||||
valueChangedImplementation();
|
||||
}
|
||||
|
||||
void MultiChangeListener::valueChangedImplementation()
|
||||
{
|
||||
}
|
||||
|
||||
AtomicChangeListener::AtomicChangeListener(std::vector<SGPropertyNode*>& nodes)
|
||||
: _dirty(false), _valid(true)
|
||||
{
|
||||
listenToProperties(nodes.begin(), nodes.end());
|
||||
}
|
||||
|
||||
void AtomicChangeListener::unregister_property(SGPropertyNode* node)
|
||||
{
|
||||
_valid = false;
|
||||
// not necessary, but good hygine
|
||||
vector<SGPropertyNode*>::iterator itr
|
||||
= find(_watched.begin(), _watched.end(), node);
|
||||
if (itr != _watched.end())
|
||||
*itr = 0;
|
||||
MultiChangeListener::unregister_property(node);
|
||||
}
|
||||
|
||||
void AtomicChangeListener::fireChangeListeners()
|
||||
{
|
||||
vector<SGSharedPtr<AtomicChangeListener> >& listeners
|
||||
= ListenerListSingleton::instance()->listeners;
|
||||
for (vector<SGSharedPtr<AtomicChangeListener> >::iterator itr = listeners.begin(),
|
||||
end = listeners.end();
|
||||
itr != end;
|
||||
++itr) {
|
||||
(*itr)->valuesChanged();
|
||||
(*itr)->_dirty = false;
|
||||
}
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
void AtomicChangeListener::valueChangedImplementation()
|
||||
{
|
||||
if (!_dirty) {
|
||||
_dirty = true;
|
||||
if (_valid)
|
||||
ListenerListSingleton::instance()->listeners.push_back(this);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomicChangeListener::valuesChanged()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
#ifndef SIMGEAR_ATOMICCHANGELISTENER_HXX
|
||||
#define SIMGEAR_ATOMICCHANGELISTENER_HXX 1
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
#include "ExtendedPropertyAdapter.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
// Performs an action when one of several nodes changes
|
||||
class MultiChangeListener : public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
MultiChangeListener();
|
||||
template<typename Pitr>
|
||||
void listenToProperties(Pitr propsBegin, Pitr propsEnd)
|
||||
{
|
||||
for (Pitr itr = propsBegin, end = propsEnd; itr != end; ++itr)
|
||||
(*itr)->addChangeListener(this);
|
||||
}
|
||||
private:
|
||||
void valueChanged(SGPropertyNode* node);
|
||||
virtual void valueChangedImplementation();
|
||||
|
||||
};
|
||||
|
||||
class AtomicChangeListener : public MultiChangeListener,
|
||||
public virtual SGReferenced
|
||||
{
|
||||
public:
|
||||
AtomicChangeListener(std::vector<SGPropertyNode*>& nodes);
|
||||
/**
|
||||
* Lookup / create child nodes from their relative names.
|
||||
*/
|
||||
template<typename Itr>
|
||||
AtomicChangeListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||
Itr childNamesEnd)
|
||||
: _dirty(false), _valid(true)
|
||||
{
|
||||
using namespace std;
|
||||
for (Itr itr = childNamesBegin, end = childNamesEnd;
|
||||
itr != end;
|
||||
++itr)
|
||||
_watched.push_back(makeNode(parent, *itr));
|
||||
listenToProperties(_watched.begin(), _watched.end());
|
||||
}
|
||||
bool isDirty() { return _dirty; }
|
||||
bool isValid() { return _valid; }
|
||||
void unregister_property(SGPropertyNode* node);
|
||||
static void fireChangeListeners();
|
||||
private:
|
||||
virtual void valueChangedImplementation();
|
||||
virtual void valuesChanged();
|
||||
bool _dirty;
|
||||
bool _valid;
|
||||
struct ListenerListSingleton : public Singleton<ListenerListSingleton>
|
||||
{
|
||||
std::vector<SGSharedPtr<AtomicChangeListener> > listeners;
|
||||
};
|
||||
protected:
|
||||
std::vector<SGPropertyNode*> _watched;
|
||||
};
|
||||
|
||||
template<typename T, typename Func>
|
||||
class ExtendedPropListener : public AtomicChangeListener
|
||||
{
|
||||
public:
|
||||
ExtendedPropListener(std::vector<SGPropertyNode*>& nodes, const Func& func,
|
||||
bool initial = false)
|
||||
: AtomicChangeListener(nodes), _func(func)
|
||||
{
|
||||
if (initial)
|
||||
valuesChanged();
|
||||
|
||||
}
|
||||
template<typename Itr>
|
||||
ExtendedPropListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||
Itr childNamesEnd, const Func& func,
|
||||
bool initial = false)
|
||||
: AtomicChangeListener(parent, childNamesBegin, childNamesEnd),
|
||||
_func(func)
|
||||
{
|
||||
if (initial)
|
||||
valuesChanged();
|
||||
}
|
||||
virtual void valuesChanged()
|
||||
{
|
||||
ExtendedPropertyAdapter<T, std::vector<SGPropertyNode*> > adaptor(_watched);
|
||||
T val = adaptor();
|
||||
_func(val);
|
||||
}
|
||||
private:
|
||||
Func _func;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX
|
||||
#define SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX 1
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
namespace props
|
||||
{
|
||||
// This should be in simgear/math/SGVec.hxx and friends
|
||||
|
||||
template<typename T> struct NumComponents;
|
||||
|
||||
template<> struct NumComponents<SGVec3d>
|
||||
{
|
||||
enum { num_components = 3 };
|
||||
};
|
||||
|
||||
template<> struct NumComponents<SGVec4d>
|
||||
{
|
||||
enum { num_components = 4 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename NodeContainer>
|
||||
class ExtendedPropertyAdapter
|
||||
{
|
||||
public:
|
||||
enum { num_components = props::NumComponents<T>::num_components };
|
||||
ExtendedPropertyAdapter(const NodeContainer& elements)
|
||||
: _elements(elements)
|
||||
{
|
||||
}
|
||||
T operator()() const
|
||||
{
|
||||
T result;
|
||||
if (_elements.size() < num_components)
|
||||
throw sg_exception();
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
result[i] = _elements[i]->getValue<double>();
|
||||
return result;
|
||||
}
|
||||
void set(const T& val)
|
||||
{
|
||||
if (_elements.size() < num_components)
|
||||
throw sg_exception();
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
_elements[i]->setValue(val[i]);
|
||||
}
|
||||
private:
|
||||
const NodeContainer& _elements;
|
||||
};
|
||||
|
||||
template<typename InIterator, typename OutIterator>
|
||||
inline void makeChildList(SGPropertyNode* prop, InIterator inBegin,
|
||||
InIterator inEnd, OutIterator outBegin)
|
||||
{
|
||||
std::transform(inBegin, inEnd, outBegin,
|
||||
boost::bind(static_cast<SGPropertyNode* (SGPropertyNode::*)(const char*, int, bool)>(&SGPropertyNode::getChild), prop, _1, 0, true));
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -5,12 +5,15 @@ lib_LIBRARIES = libsgprops.a
|
||||
include_HEADERS = \
|
||||
condition.hxx \
|
||||
props.hxx \
|
||||
props_io.hxx
|
||||
props_io.hxx \
|
||||
AtomicChangeListener.hxx \
|
||||
ExtendedPropertyAdapter.hxx
|
||||
|
||||
libsgprops_a_SOURCES = \
|
||||
condition.cxx \
|
||||
props.cxx \
|
||||
props_io.cxx
|
||||
props_io.cxx \
|
||||
AtomicChangeListener.cxx
|
||||
|
||||
noinst_PROGRAMS = props_test
|
||||
|
||||
@@ -22,4 +25,10 @@ props_test_LDADD = \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/structure/libsgstructure.a
|
||||
|
||||
if HAVE_FRAMEWORK_OSG
|
||||
props_test_LDFLAGS = $(openthreads_FRAMEWORK)
|
||||
else
|
||||
props_test_LDFLAGS = -lOpenThreads
|
||||
endif
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
||||
+15
-10
@@ -8,7 +8,7 @@
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear/compiler.h>
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
// #include <iostream>
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "props.hxx"
|
||||
#include "condition.hxx"
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
|
||||
@@ -144,8 +146,9 @@ SGOrCondition::addCondition (SGCondition * condition)
|
||||
static int
|
||||
doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
{
|
||||
using namespace simgear;
|
||||
switch (left->getType()) {
|
||||
case SGPropertyNode::BOOL: {
|
||||
case props::BOOL: {
|
||||
bool v1 = left->getBoolValue();
|
||||
bool v2 = right->getBoolValue();
|
||||
if (v1 < v2)
|
||||
@@ -156,7 +159,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::INT: {
|
||||
case props::INT: {
|
||||
int v1 = left->getIntValue();
|
||||
int v2 = right->getIntValue();
|
||||
if (v1 < v2)
|
||||
@@ -167,7 +170,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::LONG: {
|
||||
case props::LONG: {
|
||||
long v1 = left->getLongValue();
|
||||
long v2 = right->getLongValue();
|
||||
if (v1 < v2)
|
||||
@@ -178,7 +181,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::FLOAT: {
|
||||
case props::FLOAT: {
|
||||
float v1 = left->getFloatValue();
|
||||
float v2 = right->getFloatValue();
|
||||
if (v1 < v2)
|
||||
@@ -189,7 +192,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::DOUBLE: {
|
||||
case props::DOUBLE: {
|
||||
double v1 = left->getDoubleValue();
|
||||
double v2 = right->getDoubleValue();
|
||||
if (v1 < v2)
|
||||
@@ -200,9 +203,9 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
case SGPropertyNode::STRING:
|
||||
case SGPropertyNode::NONE:
|
||||
case SGPropertyNode::UNSPECIFIED: {
|
||||
case props::STRING:
|
||||
case props::NONE:
|
||||
case props::UNSPECIFIED: {
|
||||
string v1 = left->getStringValue();
|
||||
string v2 = right->getStringValue();
|
||||
if (v1 < v2)
|
||||
@@ -213,8 +216,10 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||
return SGComparisonCondition::EQUALS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw sg_exception("condition: unrecognized node type in comparison");
|
||||
}
|
||||
throw sg_exception("condition: unrecognized node type in comparison");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+818
-667
File diff suppressed because it is too large
Load Diff
+554
-126
@@ -18,6 +18,10 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#if PROPS_STANDALONE
|
||||
#else
|
||||
@@ -26,10 +30,49 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <simgear/math/SGMathFwd.hxx>
|
||||
#include <simgear/structure/SGReferenced.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
|
||||
// XXX This whole file should be in the simgear namespace, but I don't
|
||||
// have the guts yet...
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
template<typename T>
|
||||
std::istream& readFrom(std::istream& stream, T& result)
|
||||
{
|
||||
stream >> result;
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a string as an object of a given type.
|
||||
* XXX no error behavior yet.
|
||||
*
|
||||
* @tparam T the return type
|
||||
* @param str the string
|
||||
* @return the object.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T parseString(const std::string& str)
|
||||
{
|
||||
std::istringstream stream(str);
|
||||
T result;
|
||||
readFrom(stream, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Extended properties
|
||||
template<>
|
||||
std::istream& readFrom<SGVec3d>(std::istream& stream, SGVec3d& result);
|
||||
template<>
|
||||
std::istream& readFrom<SGVec4d>(std::istream& stream, SGVec4d& result);
|
||||
|
||||
|
||||
/**
|
||||
* Property value types.
|
||||
*/
|
||||
|
||||
#ifdef NONE
|
||||
#pragma warn A sloppy coder has defined NONE as a macro!
|
||||
@@ -76,6 +119,68 @@
|
||||
#undef STRING
|
||||
#endif
|
||||
|
||||
namespace props
|
||||
{
|
||||
/**
|
||||
* The possible types of an SGPropertyNode. Types that appear after
|
||||
* EXTENDED are not stored in the SGPropertyNode itself.
|
||||
*/
|
||||
enum Type {
|
||||
NONE = 0, /**< The node hasn't been assigned a value yet. */
|
||||
ALIAS, /**< The node "points" to another node. */
|
||||
BOOL,
|
||||
INT,
|
||||
LONG,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
STRING,
|
||||
UNSPECIFIED,
|
||||
EXTENDED, /**< The node's value is not stored in the property;
|
||||
* the actual value and type is retrieved from an
|
||||
* SGRawValue node. This type is never returned by @see
|
||||
* SGPropertyNode::getType.
|
||||
*/
|
||||
// Extended properties
|
||||
VEC3D,
|
||||
VEC4D
|
||||
};
|
||||
|
||||
template<typename T> struct PropertyTraits;
|
||||
|
||||
#define DEFINTERNALPROP(TYPE, PROP) \
|
||||
template<> \
|
||||
struct PropertyTraits<TYPE> \
|
||||
{ \
|
||||
static const Type type_tag = PROP; \
|
||||
enum { Internal = 1 }; \
|
||||
}
|
||||
|
||||
DEFINTERNALPROP(bool, BOOL);
|
||||
DEFINTERNALPROP(int, INT);
|
||||
DEFINTERNALPROP(long, LONG);
|
||||
DEFINTERNALPROP(float, FLOAT);
|
||||
DEFINTERNALPROP(double, DOUBLE);
|
||||
DEFINTERNALPROP(const char *, STRING);
|
||||
DEFINTERNALPROP(const char[], STRING);
|
||||
#undef DEFINTERNALPROP
|
||||
|
||||
template<>
|
||||
struct PropertyTraits<SGVec3d>
|
||||
{
|
||||
static const Type type_tag = VEC3D;
|
||||
enum { Internal = 0 };
|
||||
};
|
||||
|
||||
template<>
|
||||
struct PropertyTraits<SGVec4d>
|
||||
{
|
||||
static const Type type_tag = VEC4D;
|
||||
enum { Internal = 0 };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -90,6 +195,74 @@
|
||||
// a small performance hit for that.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Base class for SGRawValue classes that holds no type
|
||||
* information. This allows some generic manipulation of the
|
||||
* SGRawValue object.
|
||||
*/
|
||||
class SGRaw
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get the type enumeration for the raw value.
|
||||
*
|
||||
* @return the type.
|
||||
*/
|
||||
virtual simgear::props::Type getType() const = 0;
|
||||
virtual ~SGRaw() {}
|
||||
|
||||
/**
|
||||
* Create a new deep copy of this raw value.
|
||||
*
|
||||
* The copy will contain its own version of the underlying value
|
||||
* as well, and will be the same type.
|
||||
*
|
||||
* @return A deep copy of the current object.
|
||||
*/
|
||||
virtual SGRaw* clone() const = 0;
|
||||
|
||||
};
|
||||
|
||||
class SGRawExtended : public SGRaw
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Make an SGRawValueContainer from the SGRawValue.
|
||||
*
|
||||
* This is a virtual function of SGRawExtended so that
|
||||
* SGPropertyNode::untie doesn't need to know the type of an
|
||||
* extended property.
|
||||
*/
|
||||
virtual SGRawExtended* makeContainer() const = 0;
|
||||
/**
|
||||
* Write value out to a stream
|
||||
*/
|
||||
virtual std::ostream& printOn(std::ostream& stream) const = 0;
|
||||
/**
|
||||
* Read value from a stream and store it.
|
||||
*/
|
||||
virtual std::istream& readFrom(std::istream& stream) = 0;
|
||||
};
|
||||
|
||||
// Choose between different base classes based on whether the value is
|
||||
// stored internal to the property node. This frees us from defining
|
||||
// the virtual functions in the SGRawExtended interface where they
|
||||
// don't make sense, e.g. readFrom for the const char* type.
|
||||
template<typename T, int internal = simgear::props::PropertyTraits<T>::Internal>
|
||||
class SGRawBase;
|
||||
|
||||
template<typename T>
|
||||
class SGRawBase<T, 1> : public SGRaw
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class SGRawBase<T, 0> : public SGRawExtended
|
||||
{
|
||||
virtual SGRawExtended* makeContainer() const;
|
||||
virtual std::ostream& printOn(std::ostream& stream) const;
|
||||
virtual std::istream& readFrom(std::istream& stream);
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstract base class for a raw value.
|
||||
@@ -108,10 +281,7 @@
|
||||
* set, and clone the underlying value. The SGRawValue may change
|
||||
* frequently during a session as a value is retyped or bound and
|
||||
* unbound to various data source, but the abstract SGPropertyNode
|
||||
* layer insulates the application from those changes. The raw value
|
||||
* contains no facilities for data binding or for type conversion: it
|
||||
* is simply the abstraction of a primitive data type (or a compound
|
||||
* data type, in the case of a string).</p>
|
||||
* layer insulates the application from those changes.
|
||||
*
|
||||
* <p>The SGPropertyNode class always keeps a *copy* of a raw value,
|
||||
* not the original one passed to it; if you override a derived class
|
||||
@@ -127,9 +297,10 @@
|
||||
* @see SGRawValueFunctionsIndexed
|
||||
* @see SGRawValueMethods
|
||||
* @see SGRawValueMethodsIndexed
|
||||
* @see SGRawValueContainer
|
||||
*/
|
||||
template <class T>
|
||||
class SGRawValue
|
||||
class SGRawValue : public SGRawBase<T>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -142,7 +313,10 @@ public:
|
||||
* may need different kinds of default values (such as epoch for a
|
||||
* date type). The default value is used when creating new values.
|
||||
*/
|
||||
static const T DefaultValue; // Default for this kind of raw value.
|
||||
static T DefaultValue()
|
||||
{
|
||||
return T();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -184,17 +358,30 @@ public:
|
||||
|
||||
|
||||
/**
|
||||
* Create a new deep copy of this raw value.
|
||||
*
|
||||
* The copy will contain its own version of the underlying value
|
||||
* as well.
|
||||
*
|
||||
* @return A deep copy of the current object.
|
||||
* Return the type tag for this raw value type.
|
||||
*/
|
||||
virtual SGRawValue * clone () const = 0;
|
||||
virtual simgear::props::Type getType() const
|
||||
{
|
||||
return simgear::props::PropertyTraits<T>::type_tag;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Default values for every type.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<> inline bool SGRawValue<bool>::DefaultValue()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<> inline const char * SGRawValue<const char *>::DefaultValue()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* A raw value bound to a pointer.
|
||||
*
|
||||
@@ -247,8 +434,8 @@ public:
|
||||
*
|
||||
* The copy will use the same external pointer as the original.
|
||||
*/
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValuePointer<T>(_ptr);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValuePointer(_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -304,7 +491,7 @@ public:
|
||||
*/
|
||||
virtual T getValue () const {
|
||||
if (_getter) return (*_getter)();
|
||||
else return SGRawValue<T>::DefaultValue;
|
||||
else return SGRawValue<T>::DefaultValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,8 +509,8 @@ public:
|
||||
/**
|
||||
* Create a copy of this raw value, bound to the same functions.
|
||||
*/
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueFunctions<T>(_getter,_setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueFunctions(_getter,_setter);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -353,14 +540,14 @@ public:
|
||||
virtual ~SGRawValueFunctionsIndexed () {}
|
||||
virtual T getValue () const {
|
||||
if (_getter) return (*_getter)(_index);
|
||||
else return SGRawValue<T>::DefaultValue;
|
||||
else return SGRawValue<T>::DefaultValue();
|
||||
}
|
||||
virtual bool setValue (T value) {
|
||||
if (_setter) { (*_setter)(_index, value); return true; }
|
||||
else return false;
|
||||
}
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueFunctionsIndexed<T>(_index, _getter, _setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueFunctionsIndexed(_index, _getter, _setter);
|
||||
}
|
||||
private:
|
||||
int _index;
|
||||
@@ -386,14 +573,14 @@ public:
|
||||
virtual ~SGRawValueMethods () {}
|
||||
virtual T getValue () const {
|
||||
if (_getter) { return (_obj.*_getter)(); }
|
||||
else { return SGRawValue<T>::DefaultValue; }
|
||||
else { return SGRawValue<T>::DefaultValue(); }
|
||||
}
|
||||
virtual bool setValue (T value) {
|
||||
if (_setter) { (_obj.*_setter)(value); return true; }
|
||||
else return false;
|
||||
}
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueMethods<C,T>(_obj, _getter, _setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueMethods(_obj, _getter, _setter);
|
||||
}
|
||||
private:
|
||||
C &_obj;
|
||||
@@ -420,14 +607,14 @@ public:
|
||||
virtual ~SGRawValueMethodsIndexed () {}
|
||||
virtual T getValue () const {
|
||||
if (_getter) { return (_obj.*_getter)(_index); }
|
||||
else { return SGRawValue<T>::DefaultValue; }
|
||||
else { return SGRawValue<T>::DefaultValue(); }
|
||||
}
|
||||
virtual bool setValue (T value) {
|
||||
if (_setter) { (_obj.*_setter)(_index, value); return true; }
|
||||
else return false;
|
||||
}
|
||||
virtual SGRawValue<T> * clone () const {
|
||||
return new SGRawValueMethodsIndexed<C,T>(_obj, _index, _getter, _setter);
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueMethodsIndexed(_obj, _index, _getter, _setter);
|
||||
}
|
||||
private:
|
||||
C &_obj;
|
||||
@@ -436,6 +623,77 @@ private:
|
||||
setter_t _setter;
|
||||
};
|
||||
|
||||
/**
|
||||
* A raw value that contains its value. This provides a way for
|
||||
* property nodes to contain values that shouldn't be stored in the
|
||||
* property node itself.
|
||||
*/
|
||||
template <class T>
|
||||
class SGRawValueContainer : public SGRawValue<T>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Explicit constructor.
|
||||
*/
|
||||
SGRawValueContainer(const T& obj) : _obj(obj) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~SGRawValueContainer() {}
|
||||
|
||||
/**
|
||||
* Get the underlying value.
|
||||
*/
|
||||
virtual T getValue() const { return _obj; }
|
||||
|
||||
/**
|
||||
* Set the underlying value.
|
||||
*
|
||||
* This method will dereference the pointer and change the
|
||||
* variable's value.
|
||||
*/
|
||||
virtual bool setValue (T value) { _obj = value; return true; }
|
||||
|
||||
/**
|
||||
* Create a copy of this raw value.
|
||||
*/
|
||||
virtual SGRaw* clone () const {
|
||||
return new SGRawValueContainer(_obj);
|
||||
}
|
||||
|
||||
private:
|
||||
T _obj;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
SGRawExtended* SGRawBase<T, 0>::makeContainer() const
|
||||
{
|
||||
return new SGRawValueContainer<T>(static_cast<const SGRawValue<T>*>(this)
|
||||
->getValue());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& SGRawBase<T, 0>::printOn(std::ostream& stream) const
|
||||
{
|
||||
return stream << static_cast<SGRawValue<T>*>(this)->getValue();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::istream& SGRawBase<T, 0>::readFrom(std::istream& stream)
|
||||
{
|
||||
T value;
|
||||
simgear::readFrom(stream, value);
|
||||
static_cast<SGRawValue<T>*>(this)->setValue(value);
|
||||
return stream;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::ostream& SGRawBase<SGVec3d>::printOn(std::ostream& stream) const;
|
||||
template<>
|
||||
std::ostream& SGRawBase<SGVec4d>::printOn(std::ostream& stream) const;
|
||||
|
||||
|
||||
/**
|
||||
* The smart pointer that manage reference counting
|
||||
@@ -444,6 +702,11 @@ class SGPropertyNode;
|
||||
typedef SGSharedPtr<SGPropertyNode> SGPropertyNode_ptr;
|
||||
typedef SGSharedPtr<const SGPropertyNode> SGConstPropertyNode_ptr;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
typedef std::vector<SGPropertyNode_ptr> PropertyList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The property change listener interface.
|
||||
@@ -484,22 +747,6 @@ public:
|
||||
MAX_STRING_LEN = 1024
|
||||
};
|
||||
|
||||
/**
|
||||
* Property value types.
|
||||
*/
|
||||
enum Type {
|
||||
NONE = 0,
|
||||
ALIAS,
|
||||
BOOL,
|
||||
INT,
|
||||
LONG,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
STRING,
|
||||
UNSPECIFIED
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Access mode attributes.
|
||||
*
|
||||
@@ -550,7 +797,7 @@ public:
|
||||
/**
|
||||
* Test whether this node contains a primitive leaf value.
|
||||
*/
|
||||
bool hasValue () const { return (_type != NONE); }
|
||||
bool hasValue () const { return (_type != simgear::props::NONE); }
|
||||
|
||||
|
||||
/**
|
||||
@@ -558,11 +805,15 @@ public:
|
||||
*/
|
||||
const char * getName () const { return _name.c_str(); }
|
||||
|
||||
/**
|
||||
* Get the node's simple name as a string.
|
||||
*/
|
||||
const std::string& getNameString () const { return _name; }
|
||||
|
||||
/**
|
||||
* Get the node's pretty display name, with subscript when needed.
|
||||
*/
|
||||
const char * getDisplayName (bool simplify = false) const;
|
||||
std::string getDisplayName (bool simplify = false) const;
|
||||
|
||||
|
||||
/**
|
||||
@@ -591,7 +842,7 @@ public:
|
||||
/**
|
||||
* Get the number of child nodes.
|
||||
*/
|
||||
int nChildren () const { return _children.size(); }
|
||||
int nChildren () const { return (int)_children.size(); }
|
||||
|
||||
|
||||
/**
|
||||
@@ -622,21 +873,18 @@ public:
|
||||
return (getChild(name, index) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a child node after the last node with the same name.
|
||||
*/
|
||||
SGPropertyNode * addChild (const char * name);
|
||||
|
||||
/**
|
||||
* Get a child node by name and index.
|
||||
*/
|
||||
SGPropertyNode * getChild (const char * name, int index = 0,
|
||||
bool create = false);
|
||||
|
||||
/**
|
||||
* Get a child node by name and index.
|
||||
*/
|
||||
SGPropertyNode * getChild (const char* name, int index = 0,
|
||||
bool create = false);
|
||||
SGPropertyNode * getChild (const std::string& name, int index = 0,
|
||||
bool create = false)
|
||||
{ return getChild(name.c_str(), index, create); }
|
||||
|
||||
|
||||
bool create = false);
|
||||
/**
|
||||
* Get a const child node by name and index.
|
||||
*/
|
||||
@@ -652,12 +900,12 @@ public:
|
||||
/**
|
||||
* Get a vector of all children with the specified name.
|
||||
*/
|
||||
std::vector<SGPropertyNode_ptr> getChildren (const char * name) const;
|
||||
simgear::PropertyList getChildren (const char * name) const;
|
||||
|
||||
/**
|
||||
* Get a vector of all children with the specified name.
|
||||
*/
|
||||
std::vector<SGPropertyNode_ptr> getChildren (const std::string& name) const
|
||||
simgear::PropertyList getChildren (const std::string& name) const
|
||||
{ return getChildren(name.c_str()); }
|
||||
|
||||
/**
|
||||
@@ -682,15 +930,13 @@ public:
|
||||
/**
|
||||
* Remove all children with the specified name.
|
||||
*/
|
||||
std::vector<SGPropertyNode_ptr> removeChildren (const char * name,
|
||||
bool keep = true);
|
||||
|
||||
simgear::PropertyList removeChildren (const char * name, bool keep = true);
|
||||
|
||||
/**
|
||||
* Remove all children with the specified name.
|
||||
*/
|
||||
std::vector<SGPropertyNode_ptr> removeChildren (const std::string& name,
|
||||
bool keep = true)
|
||||
simgear::PropertyList removeChildren (const std::string& name,
|
||||
bool keep = true)
|
||||
{ return removeChildren(name.c_str(), keep); }
|
||||
|
||||
//
|
||||
@@ -725,7 +971,7 @@ public:
|
||||
/**
|
||||
* Test whether the node's leaf value is aliased to another's.
|
||||
*/
|
||||
bool isAlias () const { return (_type == ALIAS); }
|
||||
bool isAlias () const { return (_type == simgear::props::ALIAS); }
|
||||
|
||||
|
||||
/**
|
||||
@@ -870,7 +1116,7 @@ public:
|
||||
/**
|
||||
* Get the type of leaf value, if any, for this node.
|
||||
*/
|
||||
Type getType () const;
|
||||
simgear::props::Type getType () const;
|
||||
|
||||
|
||||
/**
|
||||
@@ -908,7 +1154,17 @@ public:
|
||||
*/
|
||||
const char * getStringValue () const;
|
||||
|
||||
|
||||
/**
|
||||
* Get a value from a node. If the actual type of the node doesn't
|
||||
* match the desired type, a conversion isn't guaranteed.
|
||||
*/
|
||||
template<typename T>
|
||||
T getValue(typename boost::enable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0) const;
|
||||
// Getter for extended property
|
||||
template<typename T>
|
||||
T getValue(typename boost::disable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0) const;
|
||||
|
||||
/**
|
||||
* Set a bool value for this node.
|
||||
@@ -957,7 +1213,27 @@ public:
|
||||
*/
|
||||
bool setUnspecifiedValue (const char * value);
|
||||
|
||||
template<typename T>
|
||||
bool setValue(const T& val,
|
||||
typename boost::enable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0);
|
||||
|
||||
template<typename T>
|
||||
bool setValue(const T& val,
|
||||
typename boost::disable_if_c<simgear::props::PropertyTraits<T>::Internal>
|
||||
::type* dummy = 0);
|
||||
|
||||
template<int N>
|
||||
bool setValue(const char (&val)[N])
|
||||
{
|
||||
return setValue(&val[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the value of the property to a stream.
|
||||
*/
|
||||
std::ostream& printOn(std::ostream& stream) const;
|
||||
|
||||
//
|
||||
// Data binding.
|
||||
//
|
||||
@@ -968,42 +1244,11 @@ public:
|
||||
*/
|
||||
bool isTied () const { return _tied; }
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external bool source.
|
||||
*/
|
||||
bool tie (const SGRawValue<bool> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external int source.
|
||||
*/
|
||||
bool tie (const SGRawValue<int> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external long int source.
|
||||
*/
|
||||
bool tie (const SGRawValue<long> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external float source.
|
||||
*/
|
||||
bool tie (const SGRawValue<float> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external double source.
|
||||
*/
|
||||
bool tie (const SGRawValue<double> &rawValue, bool useDefault = true);
|
||||
|
||||
|
||||
/**
|
||||
* Bind this node to an external string source.
|
||||
*/
|
||||
bool tie (const SGRawValue<const char *> &rawValue, bool useDefault = true);
|
||||
|
||||
/**
|
||||
* Bind this node to an external source.
|
||||
*/
|
||||
template<typename T>
|
||||
bool tie(const SGRawValue<T> &rawValue, bool useDefault = true);
|
||||
|
||||
/**
|
||||
* Unbind this node from any external data source.
|
||||
@@ -1020,12 +1265,12 @@ public:
|
||||
/**
|
||||
* Get another node's type.
|
||||
*/
|
||||
Type getType (const char * relative_path) const;
|
||||
simgear::props::Type getType (const char * relative_path) const;
|
||||
|
||||
/**
|
||||
* Get another node's type.
|
||||
*/
|
||||
Type getType (const std::string& relative_path) const
|
||||
simgear::props::Type getType (const std::string& relative_path) const
|
||||
{ return getType(relative_path.c_str()); }
|
||||
|
||||
/**
|
||||
@@ -1186,12 +1431,17 @@ public:
|
||||
*/
|
||||
bool setStringValue (const char * relative_path, const char * value);
|
||||
|
||||
bool setStringValue(const char * relative_path, const std::string& value)
|
||||
{ return setStringValue(relative_path, value.c_str()); }
|
||||
/**
|
||||
* Set another node's value as a string.
|
||||
*/
|
||||
bool setStringValue (const std::string& relative_path, const char * value)
|
||||
{ return setStringValue(relative_path.c_str(), value); }
|
||||
|
||||
bool setStringValue (const std::string& relative_path,
|
||||
const std::string& value)
|
||||
{ return setStringValue(relative_path.c_str(), value.c_str()); }
|
||||
|
||||
/**
|
||||
* Set another node's value with no specified type.
|
||||
@@ -1323,7 +1573,7 @@ public:
|
||||
/**
|
||||
* Get the number of listeners.
|
||||
*/
|
||||
int nListeners () const { return _listeners ? _listeners->size() : 0; }
|
||||
int nListeners () const { return _listeners ? (int)_listeners->size() : 0; }
|
||||
|
||||
|
||||
/**
|
||||
@@ -1349,6 +1599,16 @@ public:
|
||||
*/
|
||||
void clearValue ();
|
||||
|
||||
/**
|
||||
* Compare two property trees. The property trees are equal if: 1)
|
||||
* They have no children, and have the same type and the values are
|
||||
* equal, or 2) have the same number of children, and the
|
||||
* corresponding children in each tree are equal. "corresponding"
|
||||
* means have the same name and index.
|
||||
*
|
||||
* Attributes, removed children, and aliases aren't considered.
|
||||
*/
|
||||
static bool compare (const SGPropertyNode& lhs, const SGPropertyNode& rhs);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1359,12 +1619,13 @@ protected:
|
||||
/**
|
||||
* Protected constructor for making new nodes on demand.
|
||||
*/
|
||||
SGPropertyNode (const char * name, int index, SGPropertyNode * parent);
|
||||
|
||||
SGPropertyNode (const std::string& name, int index, SGPropertyNode * parent);
|
||||
template<typename Itr>
|
||||
SGPropertyNode (Itr begin, Itr end, int index, SGPropertyNode * parent);
|
||||
|
||||
private:
|
||||
|
||||
// Get the raw value
|
||||
// Get the raw value
|
||||
bool get_bool () const;
|
||||
int get_int () const;
|
||||
long get_long () const;
|
||||
@@ -1372,7 +1633,7 @@ private:
|
||||
double get_double () const;
|
||||
const char * get_string () const;
|
||||
|
||||
// Set the raw value
|
||||
// Set the raw value
|
||||
bool set_bool (bool value);
|
||||
bool set_int (int value);
|
||||
bool set_long (long value);
|
||||
@@ -1386,7 +1647,6 @@ private:
|
||||
*/
|
||||
const char * make_string () const;
|
||||
|
||||
|
||||
/**
|
||||
* Trace a read access.
|
||||
*/
|
||||
@@ -1409,29 +1669,23 @@ private:
|
||||
|
||||
int _index;
|
||||
std::string _name;
|
||||
mutable std::string _display_name;
|
||||
/// To avoid cyclic reference counting loops this shall not be a reference
|
||||
/// counted pointer
|
||||
SGPropertyNode * _parent;
|
||||
std::vector<SGPropertyNode_ptr> _children;
|
||||
std::vector<SGPropertyNode_ptr> _removedChildren;
|
||||
simgear::PropertyList _children;
|
||||
simgear::PropertyList _removedChildren;
|
||||
std::vector<hash_table *> _linkedNodes;
|
||||
mutable std::string _path;
|
||||
mutable std::string _buffer;
|
||||
hash_table * _path_cache;
|
||||
Type _type;
|
||||
simgear::props::Type _type;
|
||||
bool _tied;
|
||||
int _attr;
|
||||
|
||||
// The right kind of pointer...
|
||||
// The right kind of pointer...
|
||||
union {
|
||||
SGPropertyNode * alias;
|
||||
SGRawValue<bool> * bool_val;
|
||||
SGRawValue<int> * int_val;
|
||||
SGRawValue<long> * long_val;
|
||||
SGRawValue<float> * float_val;
|
||||
SGRawValue<double> * double_val;
|
||||
SGRawValue<const char *> * string_val;
|
||||
SGRaw* val;
|
||||
} _value;
|
||||
|
||||
union {
|
||||
@@ -1447,8 +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); }
|
||||
bool remove_linked_node (hash_table * node);
|
||||
|
||||
@@ -1505,10 +1759,21 @@ private:
|
||||
unsigned int _data_length;
|
||||
bucket ** _data;
|
||||
};
|
||||
|
||||
// Pass name as a pair of iterators
|
||||
template<typename Itr>
|
||||
SGPropertyNode * getChildImpl (Itr begin, Itr end, int index = 0, bool create = false);
|
||||
// very internal method
|
||||
template<typename Itr>
|
||||
SGPropertyNode* getExistingChild (Itr begin, Itr end, int index, bool create);
|
||||
// very internal path parsing function
|
||||
template<typename SplitItr>
|
||||
friend SGPropertyNode* find_node_aux(SGPropertyNode * current, SplitItr& itr,
|
||||
bool create, int last_index);
|
||||
// For boost
|
||||
friend size_t hash_value(const SGPropertyNode& node);
|
||||
};
|
||||
|
||||
// Convenice functions for use in templates
|
||||
// Convenience functions for use in templates
|
||||
template<typename T>
|
||||
T getValue(const SGPropertyNode*);
|
||||
|
||||
@@ -1574,6 +1839,169 @@ inline bool setValue (SGPropertyNode* node, const std::string& value)
|
||||
return node->setStringValue(value.c_str());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SGPropertyNode::tie(const SGRawValue<T> &rawValue, bool useDefault)
|
||||
{
|
||||
using namespace simgear::props;
|
||||
if (_type == ALIAS || _tied)
|
||||
return false;
|
||||
|
||||
useDefault = useDefault && hasValue();
|
||||
T old_val = SGRawValue<T>::DefaultValue();
|
||||
if (useDefault)
|
||||
old_val = getValue<T>(this);
|
||||
clearValue();
|
||||
if (PropertyTraits<T>::Internal)
|
||||
_type = PropertyTraits<T>::type_tag;
|
||||
else
|
||||
_type = EXTENDED;
|
||||
_tied = true;
|
||||
_value.val = rawValue.clone();
|
||||
if (useDefault)
|
||||
setValue(old_val);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool SGPropertyNode::tie (const SGRawValue<const char *> &rawValue,
|
||||
bool useDefault);
|
||||
|
||||
template<typename T>
|
||||
T SGPropertyNode::getValue(typename boost::disable_if_c<simgear::props
|
||||
::PropertyTraits<T>::Internal>::type* dummy) const
|
||||
{
|
||||
using namespace simgear::props;
|
||||
if (_attr == (READ|WRITE) && _type == EXTENDED
|
||||
&& _value.val->getType() == PropertyTraits<T>::type_tag) {
|
||||
return static_cast<SGRawValue<T>*>(_value.val)->getValue();
|
||||
}
|
||||
if (getAttribute(TRACE_READ))
|
||||
trace_read();
|
||||
if (!getAttribute(READ))
|
||||
return SGRawValue<T>::DefaultValue();
|
||||
switch (_type) {
|
||||
case EXTENDED:
|
||||
if (_value.val->getType() == PropertyTraits<T>::type_tag)
|
||||
return static_cast<SGRawValue<T>*>(_value.val)->getValue();
|
||||
break;
|
||||
case STRING:
|
||||
case UNSPECIFIED:
|
||||
return simgear::parseString<T>(make_string());
|
||||
break;
|
||||
default: // avoid compiler warning
|
||||
break;
|
||||
}
|
||||
return SGRawValue<T>::DefaultValue();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T SGPropertyNode::getValue(typename boost::enable_if_c<simgear::props
|
||||
::PropertyTraits<T>::Internal>::type* dummy) const
|
||||
{
|
||||
return ::getValue<T>(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SGPropertyNode::setValue(const T& val,
|
||||
typename boost::disable_if_c<simgear::props
|
||||
::PropertyTraits<T>::Internal>::type* dummy)
|
||||
{
|
||||
using namespace simgear::props;
|
||||
if (_attr == (READ|WRITE) && _type == EXTENDED
|
||||
&& _value.val->getType() == PropertyTraits<T>::type_tag) {
|
||||
static_cast<SGRawValue<T>*>(_value.val)->setValue(val);
|
||||
return true;
|
||||
}
|
||||
if (getAttribute(WRITE)
|
||||
&& ((_type == EXTENDED
|
||||
&& _value.val->getType() == PropertyTraits<T>::type_tag)
|
||||
|| _type == NONE || _type == UNSPECIFIED)) {
|
||||
if (_type == NONE || _type == UNSPECIFIED) {
|
||||
clearValue();
|
||||
_type = EXTENDED;
|
||||
_value.val = new SGRawValueContainer<T>(val);
|
||||
} else {
|
||||
static_cast<SGRawValue<T>*>(_value.val)->setValue(val);
|
||||
}
|
||||
if (getAttribute(TRACE_WRITE))
|
||||
trace_write();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool SGPropertyNode::setValue(const T& val,
|
||||
typename boost::enable_if_c<simgear::props
|
||||
::PropertyTraits<T>::Internal>::type* dummy)
|
||||
{
|
||||
return ::setValue(this, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for creation of a child property node.
|
||||
*/
|
||||
inline SGPropertyNode* makeChild(SGPropertyNode* parent, const char* name,
|
||||
int index = 0)
|
||||
{
|
||||
return parent->getChild(name, index, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for creation of a child property node using a
|
||||
* relative path.
|
||||
*/
|
||||
namespace simgear
|
||||
{
|
||||
template<typename StringType>
|
||||
inline SGPropertyNode* makeNode(SGPropertyNode* parent, const StringType& name)
|
||||
{
|
||||
return parent->getNode(name, true);
|
||||
}
|
||||
}
|
||||
|
||||
// For boost::hash
|
||||
size_t hash_value(const SGPropertyNode& node);
|
||||
|
||||
// Helper comparison and hash functions for common cases
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
namespace props
|
||||
{
|
||||
struct Compare
|
||||
{
|
||||
bool operator()(const SGPropertyNode* lhs, const SGPropertyNode* rhs) const
|
||||
{
|
||||
return SGPropertyNode::compare(*lhs, *rhs);
|
||||
}
|
||||
bool operator()(SGPropertyNode_ptr lhs, const SGPropertyNode* rhs) const
|
||||
{
|
||||
return SGPropertyNode::compare(*lhs, *rhs);
|
||||
}
|
||||
bool operator()(const SGPropertyNode* lhs, SGPropertyNode_ptr rhs) const
|
||||
{
|
||||
return SGPropertyNode::compare(*lhs, *rhs);
|
||||
}
|
||||
bool operator()(SGPropertyNode_ptr lhs, SGPropertyNode_ptr rhs) const
|
||||
{
|
||||
return SGPropertyNode::compare(*lhs, *rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct Hash
|
||||
{
|
||||
size_t operator()(const SGPropertyNode* node) const
|
||||
{
|
||||
return hash_value(*node);
|
||||
}
|
||||
size_t operator()(SGPropertyNode_ptr node) const
|
||||
{
|
||||
return hash_value(*node);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // __PROPS_HXX
|
||||
|
||||
// end of props.hxx
|
||||
|
||||
+70
-33
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
|
||||
@@ -27,6 +28,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring> // strcmp()
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
@@ -52,8 +54,11 @@ class PropsVisitor : public XMLVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
PropsVisitor (SGPropertyNode * root, const string &base, int default_mode = 0)
|
||||
: _default_mode(default_mode), _root(root), _level(0), _base(base), _hasException(false) {}
|
||||
PropsVisitor (SGPropertyNode * root, const string &base, int default_mode = 0,
|
||||
bool extended = false)
|
||||
: _default_mode(default_mode), _root(root), _level(0), _base(base),
|
||||
_hasException(false), _extended(extended)
|
||||
{}
|
||||
|
||||
virtual ~PropsVisitor () {}
|
||||
|
||||
@@ -110,6 +115,7 @@ private:
|
||||
string _base;
|
||||
sg_io_exception _exception;
|
||||
bool _hasException;
|
||||
bool _extended;
|
||||
};
|
||||
|
||||
void
|
||||
@@ -167,7 +173,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
|
||||
SGPath path(SGPath(_base).dir());
|
||||
path.append(attval);
|
||||
try {
|
||||
readProperties(path.str(), _root);
|
||||
readProperties(path.str(), _root, 0, _extended);
|
||||
} catch (sg_io_exception &e) {
|
||||
setException(e);
|
||||
}
|
||||
@@ -181,16 +187,17 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
|
||||
// Get the index.
|
||||
attval = atts.getValue("n");
|
||||
int index = 0;
|
||||
string strName(name);
|
||||
if (attval != 0) {
|
||||
index = atoi(attval);
|
||||
st.counters[name] = SG_MAX2(st.counters[name], index+1);
|
||||
st.counters[strName] = SG_MAX2(st.counters[strName], index+1);
|
||||
} else {
|
||||
index = st.counters[name];
|
||||
st.counters[name]++;
|
||||
index = st.counters[strName];
|
||||
st.counters[strName]++;
|
||||
}
|
||||
|
||||
// Got the index, so grab the node.
|
||||
SGPropertyNode * node = st.node->getChild(name, index, true);
|
||||
SGPropertyNode * node = st.node->getChild(strName, index, true);
|
||||
if (!node->getAttribute(SGPropertyNode::WRITE)) {
|
||||
SG_LOG(SG_INPUT, SG_ALERT, "Not overwriting write-protected property "
|
||||
<< node->getPath(true));
|
||||
@@ -235,7 +242,7 @@ PropsVisitor::startElement (const char * name, const XMLAttributes &atts)
|
||||
SGPath path(SGPath(_base).dir());
|
||||
path.append(attval);
|
||||
try {
|
||||
readProperties(path.str(), node);
|
||||
readProperties(path.str(), node, 0, _extended);
|
||||
} catch (sg_io_exception &e) {
|
||||
setException(e);
|
||||
}
|
||||
@@ -275,6 +282,12 @@ PropsVisitor::endElement (const char * name)
|
||||
ret = st.node->setDoubleValue(strtod(_data.c_str(), 0));
|
||||
} else if (st.type == "string") {
|
||||
ret = st.node->setStringValue(_data.c_str());
|
||||
} else if (st.type == "vec3d" && _extended) {
|
||||
ret = st.node
|
||||
->setValue(simgear::parseString<SGVec3d>(_data));
|
||||
} else if (st.type == "vec4d" && _extended) {
|
||||
ret = st.node
|
||||
->setValue(simgear::parseString<SGVec4d>(_data));
|
||||
} else if (st.type == "unspecified") {
|
||||
ret = st.node->setUnspecifiedValue(_data.c_str());
|
||||
} else if (_level == 1) {
|
||||
@@ -344,9 +357,9 @@ PropsVisitor::warning (const char * message, int line, int column)
|
||||
*/
|
||||
void
|
||||
readProperties (istream &input, SGPropertyNode * start_node,
|
||||
const string &base, int default_mode)
|
||||
const string &base, int default_mode, bool extended)
|
||||
{
|
||||
PropsVisitor visitor(start_node, base, default_mode);
|
||||
PropsVisitor visitor(start_node, base, default_mode, extended);
|
||||
readXML(input, visitor, base);
|
||||
if (visitor.hasException())
|
||||
throw visitor.getException();
|
||||
@@ -362,9 +375,9 @@ readProperties (istream &input, SGPropertyNode * start_node,
|
||||
*/
|
||||
void
|
||||
readProperties (const string &file, SGPropertyNode * start_node,
|
||||
int default_mode)
|
||||
int default_mode, bool extended)
|
||||
{
|
||||
PropsVisitor visitor(start_node, file, default_mode);
|
||||
PropsVisitor visitor(start_node, file, default_mode, extended);
|
||||
readXML(file, visitor);
|
||||
if (visitor.hasException())
|
||||
throw visitor.getException();
|
||||
@@ -380,9 +393,10 @@ readProperties (const string &file, SGPropertyNode * start_node,
|
||||
* @return true if the read succeeded, false otherwise.
|
||||
*/
|
||||
void readProperties (const char *buf, const int size,
|
||||
SGPropertyNode * start_node, int default_mode)
|
||||
SGPropertyNode * start_node, int default_mode,
|
||||
bool extended)
|
||||
{
|
||||
PropsVisitor visitor(start_node, "", default_mode);
|
||||
PropsVisitor visitor(start_node, "", default_mode, extended);
|
||||
readXML(buf, size, visitor);
|
||||
if (visitor.hasException())
|
||||
throw visitor.getException();
|
||||
@@ -399,26 +413,33 @@ void readProperties (const char *buf, const int size,
|
||||
* Return the type name.
|
||||
*/
|
||||
static const char *
|
||||
getTypeName (SGPropertyNode::Type type)
|
||||
getTypeName (simgear::props::Type type)
|
||||
{
|
||||
using namespace simgear;
|
||||
switch (type) {
|
||||
case SGPropertyNode::UNSPECIFIED:
|
||||
case props::UNSPECIFIED:
|
||||
return "unspecified";
|
||||
case SGPropertyNode::BOOL:
|
||||
case props::BOOL:
|
||||
return "bool";
|
||||
case SGPropertyNode::INT:
|
||||
case props::INT:
|
||||
return "int";
|
||||
case SGPropertyNode::LONG:
|
||||
case props::LONG:
|
||||
return "long";
|
||||
case SGPropertyNode::FLOAT:
|
||||
case props::FLOAT:
|
||||
return "float";
|
||||
case SGPropertyNode::DOUBLE:
|
||||
case props::DOUBLE:
|
||||
return "double";
|
||||
case SGPropertyNode::STRING:
|
||||
case props::STRING:
|
||||
return "string";
|
||||
case SGPropertyNode::ALIAS:
|
||||
case SGPropertyNode::NONE:
|
||||
case props::VEC3D:
|
||||
return "vec3d";
|
||||
case props::VEC4D:
|
||||
return "vec4d";
|
||||
case props::ALIAS:
|
||||
case props::NONE:
|
||||
return "unspecified";
|
||||
default: // avoid compiler warning
|
||||
break;
|
||||
}
|
||||
|
||||
// keep the compiler from squawking
|
||||
@@ -524,7 +545,7 @@ writeNode (ostream &output, const SGPropertyNode * node,
|
||||
output << " alias=\"" << node->getAliasTarget()->getPath()
|
||||
<< "\"/>" << endl;
|
||||
} else {
|
||||
if (node->getType() != SGPropertyNode::UNSPECIFIED)
|
||||
if (node->getType() != simgear::props::UNSPECIFIED)
|
||||
output << " type=\"" << getTypeName(node->getType()) << '"';
|
||||
output << '>';
|
||||
writeData(output, node->getStringValue());
|
||||
@@ -581,6 +602,13 @@ writeProperties (const string &file, const SGPropertyNode * start_node,
|
||||
}
|
||||
}
|
||||
|
||||
// Another variation, useful when called from gdb
|
||||
void
|
||||
writeProperties (const char* file, const SGPropertyNode * start_node)
|
||||
{
|
||||
writeProperties(string(file), start_node, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -599,40 +627,49 @@ writeProperties (const string &file, const SGPropertyNode * start_node,
|
||||
bool
|
||||
copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
|
||||
{
|
||||
using namespace simgear;
|
||||
bool retval = true;
|
||||
|
||||
// First, copy the actual value,
|
||||
// if any.
|
||||
if (in->hasValue()) {
|
||||
switch (in->getType()) {
|
||||
case SGPropertyNode::BOOL:
|
||||
case props::BOOL:
|
||||
if (!out->setBoolValue(in->getBoolValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::INT:
|
||||
case props::INT:
|
||||
if (!out->setIntValue(in->getIntValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::LONG:
|
||||
case props::LONG:
|
||||
if (!out->setLongValue(in->getLongValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::FLOAT:
|
||||
case props::FLOAT:
|
||||
if (!out->setFloatValue(in->getFloatValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::DOUBLE:
|
||||
case props::DOUBLE:
|
||||
if (!out->setDoubleValue(in->getDoubleValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::STRING:
|
||||
case props::STRING:
|
||||
if (!out->setStringValue(in->getStringValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case SGPropertyNode::UNSPECIFIED:
|
||||
case props::UNSPECIFIED:
|
||||
if (!out->setUnspecifiedValue(in->getStringValue()))
|
||||
retval = false;
|
||||
break;
|
||||
case props::VEC3D:
|
||||
if (!out->setValue(in->getValue<SGVec3d>()))
|
||||
retval = false;
|
||||
break;
|
||||
case props::VEC4D:
|
||||
if (!out->setValue(in->getValue<SGVec4d>()))
|
||||
retval = false;
|
||||
break;
|
||||
default:
|
||||
if (in->isAlias())
|
||||
break;
|
||||
@@ -649,7 +686,7 @@ copyProperties (const SGPropertyNode *in, SGPropertyNode *out)
|
||||
int nChildren = in->nChildren();
|
||||
for (int i = 0; i < nChildren; i++) {
|
||||
const SGPropertyNode * in_child = in->getChild(i);
|
||||
SGPropertyNode * out_child = out->getChild(in_child->getName(),
|
||||
SGPropertyNode * out_child = out->getChild(in_child->getNameString(),
|
||||
in_child->getIndex(),
|
||||
true);
|
||||
if (!copyProperties(in_child, out_child))
|
||||
|
||||
@@ -26,21 +26,23 @@
|
||||
* Read properties from an XML input stream.
|
||||
*/
|
||||
void readProperties (std::istream &input, SGPropertyNode * start_node,
|
||||
const std::string &base = "", int default_mode = 0);
|
||||
const std::string &base = "", int default_mode = 0,
|
||||
bool extended = false);
|
||||
|
||||
|
||||
/**
|
||||
* Read properties from an XML file.
|
||||
*/
|
||||
void readProperties (const std::string &file, SGPropertyNode * start_node,
|
||||
int default_mode = 0);
|
||||
int default_mode = 0, bool extended = false);
|
||||
|
||||
|
||||
/**
|
||||
* Read properties from an in-memory buffer.
|
||||
*/
|
||||
void readProperties (const char *buf, const int size,
|
||||
SGPropertyNode * start_node, int default_mode = 0);
|
||||
SGPropertyNode * start_node, int default_mode = 0,
|
||||
bool extended = false);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -324,6 +324,26 @@ test_property_nodes ()
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
void test_addChild()
|
||||
{
|
||||
SGPropertyNode root;
|
||||
|
||||
cout << "Testing the addChild function " << endl;
|
||||
cout << "Created root node " << root.getPath() << endl;
|
||||
|
||||
SGPropertyNode *test = root.getChild("test", 0, true);
|
||||
SGPropertyNode *n = test->getNode("foo", true);
|
||||
n->getChild("child", 1, true)->setIntValue(1);
|
||||
n->getChild("child", 2, true)->setIntValue(2);
|
||||
n->getChild("child", 4, true)->setIntValue(2);
|
||||
dump_node(&root);
|
||||
|
||||
SGPropertyNode *ch = n->addChild("child");
|
||||
ch->setIntValue(3);
|
||||
cerr << endl << "ADDED: " << ch->getPath() << endl << endl;
|
||||
dump_node(&root);
|
||||
}
|
||||
|
||||
|
||||
int main (int ac, char ** av)
|
||||
{
|
||||
@@ -342,5 +362,7 @@ int main (int ac, char ** av)
|
||||
}
|
||||
}
|
||||
|
||||
test_addChild();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -31,4 +31,5 @@ routetest_LDADD = \
|
||||
libsgroute.a \
|
||||
$(top_builddir)/simgear/math/libsgmath.a \
|
||||
$(top_builddir)/simgear/debug/libsgdebug.a \
|
||||
$(top_builddir)/simgear/structure/libsgstructure.a \
|
||||
$(base_LIBS)
|
||||
|
||||
+26
-44
@@ -20,6 +20,9 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <plib/sg.h>
|
||||
|
||||
@@ -38,51 +41,22 @@ SGRoute::SGRoute() {
|
||||
SGRoute::~SGRoute() {
|
||||
}
|
||||
|
||||
|
||||
// Calculate perpendicular distance from the current route segment
|
||||
// This routine assumes all points are laying on a flat plane and
|
||||
// ignores the altitude (or Z) dimension. For best results, use with
|
||||
// CARTESIAN way points.
|
||||
double SGRoute::distance_off_route( double x, double y ) const {
|
||||
if ( current_wp > 0 ) {
|
||||
int n0 = current_wp - 1;
|
||||
int n1 = current_wp;
|
||||
sgdVec3 p, p0, p1, d;
|
||||
sgdSetVec3( p, x, y, 0.0 );
|
||||
sgdSetVec3( p0,
|
||||
route[n0].get_target_lon(), route[n0].get_target_lat(),
|
||||
0.0 );
|
||||
sgdSetVec3( p1,
|
||||
route[n1].get_target_lon(), route[n1].get_target_lat(),
|
||||
0.0 );
|
||||
sgdSubVec3( d, p0, p1 );
|
||||
|
||||
return sqrt( sgdClosestPointToLineDistSquared( p, p0, d ) );
|
||||
|
||||
} else {
|
||||
// We are tracking the first waypoint so there is no route
|
||||
// segment. If you add the current location as the first
|
||||
// waypoint and the actual waypoint as the second, then we
|
||||
// will have a route segment and calculate distance from it.
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Update the length of the leg ending at waypoint index */
|
||||
void SGRoute::update_distance(int index)
|
||||
void SGRoute::update_distance_and_track(int index)
|
||||
{
|
||||
SGWayPoint& curr = route[ index ];
|
||||
double course, dist;
|
||||
SGWayPoint& curr = route[ index ];
|
||||
double course, dist;
|
||||
|
||||
if ( index == 0 ) {
|
||||
dist = 0;
|
||||
} else {
|
||||
const SGWayPoint& prev = route[ index - 1 ];
|
||||
curr.CourseAndDistance( prev, &course, &dist );
|
||||
}
|
||||
if ( index == 0 ) {
|
||||
dist = 0;
|
||||
course = 0.0;
|
||||
} else {
|
||||
const SGWayPoint& prev = route[index - 1];
|
||||
curr.CourseAndDistance( prev, &course, &dist );
|
||||
}
|
||||
|
||||
curr.set_distance( dist );
|
||||
curr.set_distance(dist);
|
||||
curr.set_track(course);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,9 +71,9 @@ void SGRoute::add_waypoint( const SGWayPoint &wp, int n ) {
|
||||
} else {
|
||||
route.insert( route.begin() + n, 1, wp );
|
||||
// update distance of next leg if not at end of route
|
||||
update_distance( n + 1 );
|
||||
update_distance_and_track( n + 1 );
|
||||
}
|
||||
update_distance( n );
|
||||
update_distance_and_track( n );
|
||||
}
|
||||
|
||||
/** Delete waypoint with index n (last one if n < 0) */
|
||||
@@ -113,5 +87,13 @@ void SGRoute::delete_waypoint( int n ) {
|
||||
route.erase( route.begin() + n );
|
||||
// update distance of next leg if not at end of route
|
||||
if ( n < size - 1 )
|
||||
update_distance( n );
|
||||
update_distance_and_track( n );
|
||||
}
|
||||
|
||||
double SGRoute::total_distance() const {
|
||||
double total = 0.0;
|
||||
for (unsigned int i=0; i<route.size(); ++i) {
|
||||
total += route[i].get_distance();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
+20
-7
@@ -52,7 +52,7 @@ private:
|
||||
route_list route;
|
||||
int current_wp;
|
||||
|
||||
void update_distance(int index);
|
||||
void update_distance_and_track(int index);
|
||||
|
||||
public:
|
||||
|
||||
@@ -102,6 +102,22 @@ public:
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
inline SGWayPoint get_previous() const {
|
||||
if ( (current_wp > 0) && (current_wp < (int)route.size()) ) {
|
||||
return route[current_wp - 1];
|
||||
} else {
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
inline SGWayPoint get_next() const {
|
||||
if ( (current_wp + 1) < (int)route.size() ) {
|
||||
return route[current_wp+1];
|
||||
} else {
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current waypoint
|
||||
@@ -142,14 +158,11 @@ public:
|
||||
|
||||
/** Delete waypoint waypoint with index n (last one if n < 0) */
|
||||
void delete_waypoint( int n = 0 );
|
||||
|
||||
|
||||
/**
|
||||
* Calculate perpendicular distance from the current route segment
|
||||
* This routine assumes all points are laying on a flat plane and
|
||||
* ignores the altitude (or Z) dimension. For most accurate
|
||||
* results, use with CARTESIAN way points.
|
||||
* Helper, sum the distance members of each waypoint
|
||||
*/
|
||||
double distance_off_route( double x, double y ) const;
|
||||
double total_distance() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ void dump_route(const SGRoute& route, const char* message)
|
||||
int main()
|
||||
{
|
||||
SGRoute route;
|
||||
|
||||
/*
|
||||
route.add_waypoint( SGWayPoint(0, 0, 0, SGWayPoint::CARTESIAN, "Start") );
|
||||
route.add_waypoint( SGWayPoint(1, 0, 0, SGWayPoint::CARTESIAN, "1") );
|
||||
route.add_waypoint( SGWayPoint(2, 0, 0, SGWayPoint::CARTESIAN, "2") );
|
||||
@@ -48,6 +48,6 @@ int main()
|
||||
|
||||
route.add_waypoint(wp2, 3);
|
||||
dump_route(route, "added back WP2 after WP3");
|
||||
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
+24
-32
@@ -29,23 +29,38 @@
|
||||
|
||||
#include "waypoint.hxx"
|
||||
|
||||
using std::string;
|
||||
|
||||
// Constructor
|
||||
SGWayPoint::SGWayPoint( const double lon, const double lat, const double alt,
|
||||
const modetype m, const string& s, const string& n ) {
|
||||
target_lon = lon;
|
||||
target_lat = lat;
|
||||
target_alt = alt;
|
||||
mode = m;
|
||||
id = s;
|
||||
name = n;
|
||||
const modetype, const string& s, const string& n ) :
|
||||
pos(SGGeod::fromDegM(lon, lat, alt)),
|
||||
id(s),
|
||||
name(n),
|
||||
_distance(0.0),
|
||||
_track(0.0),
|
||||
_speed(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
SGWayPoint::SGWayPoint(const SGGeod& geod, const string& s, const string& n ) :
|
||||
pos(geod),
|
||||
id(s),
|
||||
name(n),
|
||||
_distance(0.0),
|
||||
_track(0.0),
|
||||
_speed(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
SGWayPoint::~SGWayPoint() {
|
||||
}
|
||||
|
||||
void SGWayPoint::CourseAndDistance(const SGGeod& cur, double& course, double& dist ) const {
|
||||
double reverse;
|
||||
SGGeodesy::inverse(cur, pos, course, reverse, dist);
|
||||
}
|
||||
|
||||
// Calculate course and distances. For WGS84 and SPHERICAL
|
||||
// coordinates lat, lon, and course are in degrees, alt and distance
|
||||
@@ -55,34 +70,11 @@ void SGWayPoint::CourseAndDistance( const double cur_lon,
|
||||
const double cur_lat,
|
||||
const double cur_alt,
|
||||
double *course, double *dist ) const {
|
||||
if ( mode == WGS84 ) {
|
||||
double reverse;
|
||||
geo_inverse_wgs_84( cur_alt, cur_lat, cur_lon, target_lat, target_lon,
|
||||
course, &reverse, dist );
|
||||
} else if ( mode == SPHERICAL ) {
|
||||
Point3D current( cur_lon * SGD_DEGREES_TO_RADIANS, cur_lat * SGD_DEGREES_TO_RADIANS, 0.0 );
|
||||
Point3D target( target_lon * SGD_DEGREES_TO_RADIANS, target_lat * SGD_DEGREES_TO_RADIANS, 0.0 );
|
||||
calc_gc_course_dist( current, target, course, dist );
|
||||
*course = 360.0 - *course * SGD_RADIANS_TO_DEGREES;
|
||||
} else if ( mode == CARTESIAN ) {
|
||||
double dx = target_lon - cur_lon;
|
||||
double dy = target_lat - cur_lat;
|
||||
*course = -atan2( dy, dx ) * SGD_RADIANS_TO_DEGREES - 90;
|
||||
while ( *course < 0 ) {
|
||||
*course += 360.0;
|
||||
}
|
||||
while ( *course > 360.0 ) {
|
||||
*course -= 360.0;
|
||||
}
|
||||
*dist = sqrt( dx * dx + dy * dy );
|
||||
}
|
||||
CourseAndDistance(SGGeod::fromDegM(cur_lon, cur_lat, cur_alt), *course, *dist);
|
||||
}
|
||||
|
||||
// Calculate course and distances between two waypoints
|
||||
void SGWayPoint::CourseAndDistance( const SGWayPoint &wp,
|
||||
double *course, double *dist ) const {
|
||||
CourseAndDistance( wp.get_target_lon(),
|
||||
wp.get_target_lat(),
|
||||
wp.get_target_alt(),
|
||||
course, dist );
|
||||
CourseAndDistance( wp.get_target(), *course, *dist );
|
||||
}
|
||||
|
||||
+36
-34
@@ -27,17 +27,12 @@
|
||||
#ifndef _WAYPOINT_HXX
|
||||
#define _WAYPOINT_HXX
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <string>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
|
||||
using std::string;
|
||||
#include <string>
|
||||
|
||||
|
||||
/**
|
||||
@@ -57,27 +52,21 @@ public:
|
||||
* the world is a perfect sphere. This is less compuntationally
|
||||
* expensive than using wgs84 math and still a fairly good
|
||||
* approximation of the real world, especially over shorter distances.
|
||||
* <li> CARTESIAN requests all math be done assuming the coordinates specify
|
||||
* position in a Z = up world.
|
||||
*/
|
||||
enum modetype {
|
||||
WGS84 = 0,
|
||||
SPHERICAL = 1,
|
||||
CARTESIAN = 2
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
modetype mode;
|
||||
|
||||
double target_lon;
|
||||
double target_lat;
|
||||
double target_alt;
|
||||
double distance;
|
||||
|
||||
string id;
|
||||
string name;
|
||||
|
||||
SGGeod pos;
|
||||
std::string id;
|
||||
std::string name;
|
||||
|
||||
// route data associated with the waypoint
|
||||
double _distance;
|
||||
double _track;
|
||||
double _speed;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -91,7 +80,12 @@ public:
|
||||
*/
|
||||
SGWayPoint( const double lon = 0.0, const double lat = 0.0,
|
||||
const double alt = 0.0, const modetype m = WGS84,
|
||||
const string& s = "", const string& n = "" );
|
||||
const std::string& s = "", const std::string& n = "" );
|
||||
|
||||
/**
|
||||
* Construct from a geodetic position, in WGS84 coordinates
|
||||
*/
|
||||
SGWayPoint(const SGGeod& pos, const std::string& s, const std::string& n);
|
||||
|
||||
/** Destructor */
|
||||
~SGWayPoint();
|
||||
@@ -112,6 +106,9 @@ public:
|
||||
const double cur_alt,
|
||||
double *course, double *dist ) const;
|
||||
|
||||
void CourseAndDistance(const SGGeod& current,
|
||||
double& course, double& dist ) const;
|
||||
|
||||
/**
|
||||
* Calculate course and distances between a specified starting waypoint
|
||||
* and this waypoint.
|
||||
@@ -122,17 +119,16 @@ public:
|
||||
void CourseAndDistance( const SGWayPoint &wp,
|
||||
double *course, double *dist ) const;
|
||||
|
||||
/** @return waypoint mode */
|
||||
inline modetype get_mode() const { return mode; }
|
||||
|
||||
/** @return waypoint longitude */
|
||||
inline double get_target_lon() const { return target_lon; }
|
||||
inline double get_target_lon() const { return pos.getLongitudeDeg(); }
|
||||
|
||||
/** @return waypoint latitude */
|
||||
inline double get_target_lat() const { return target_lat; }
|
||||
inline double get_target_lat() const { return pos.getLatitudeDeg(); }
|
||||
|
||||
/** @return waypoint altitude */
|
||||
inline double get_target_alt() const { return target_alt; }
|
||||
inline double get_target_alt() const { return pos.getElevationM(); }
|
||||
|
||||
inline const SGGeod& get_target() const { return pos; }
|
||||
|
||||
/**
|
||||
* This value is not calculated by this class. It is simply a
|
||||
@@ -144,19 +140,25 @@ public:
|
||||
* is for your convenience only.
|
||||
* @return waypoint distance holder (what ever the user has stashed here)
|
||||
*/
|
||||
inline double get_distance() const { return distance; }
|
||||
inline double get_distance() const { return _distance; }
|
||||
|
||||
/**
|
||||
* Set the waypoint distance value to a value of our choice.
|
||||
* @param d distance
|
||||
*/
|
||||
inline void set_distance( double d ) { distance = d; }
|
||||
inline void set_distance( double d ) { _distance = d; }
|
||||
|
||||
inline double get_track() const { return _track; }
|
||||
inline void set_track(double t) { _track = t; }
|
||||
|
||||
inline double get_speed() const { return _speed; }
|
||||
inline void set_speed(double v) { _speed = v; }
|
||||
|
||||
/** @return waypoint id */
|
||||
inline const string& get_id() const { return id; }
|
||||
inline const std::string& get_id() const { return id; }
|
||||
|
||||
/** @return waypoint name */
|
||||
inline const string& get_name() const { return name; }
|
||||
inline const std::string& get_name() const { return name; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using std::endl;
|
||||
|
||||
int main() {
|
||||
SGWayPoint a1(-93.216923, 44.880547, 0.0, SGWayPoint::WGS84, "KMSP");
|
||||
SGWayPoint a2(-93.216923, 44.880547, 0.0, SGWayPoint::SPHERICAL, "KMSP");
|
||||
|
||||
|
||||
// KMSN (Madison)
|
||||
double cur_lon = -89.336939;
|
||||
@@ -24,43 +24,15 @@ int main() {
|
||||
cout << "Distance to " << a1.get_id() << " is " << distance * SG_METER_TO_NM
|
||||
<< endl;
|
||||
|
||||
a2.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << a2.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << a2.get_id() << " is " << distance * SG_METER_TO_NM
|
||||
<< endl;
|
||||
cout << endl;
|
||||
|
||||
SGWayPoint b1(-88.237037, 43.041038, 0.0, SGWayPoint::WGS84, "KUES");
|
||||
SGWayPoint b2(-88.237037, 43.041038, 0.0, SGWayPoint::SPHERICAL, "KUES");
|
||||
|
||||
|
||||
b1.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << b1.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << b1.get_id() << " is " << distance * SG_METER_TO_NM
|
||||
<< endl;
|
||||
|
||||
b2.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << b2.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << b2.get_id() << " is " << distance * SG_METER_TO_NM
|
||||
<< endl;
|
||||
cout << endl;
|
||||
|
||||
cur_lon = 10;
|
||||
cur_lat = 10;
|
||||
|
||||
SGWayPoint c1(-20, 10, 0, SGWayPoint::CARTESIAN, "Due East");
|
||||
c1.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << c1.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << c1.get_id() << " is " << distance << endl;
|
||||
|
||||
SGWayPoint c2(20, 20, 0, SGWayPoint::CARTESIAN, "Due SW");
|
||||
c2.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << c2.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << c2.get_id() << " is " << distance << endl;
|
||||
|
||||
SGWayPoint c3(20, 0, 0, SGWayPoint::CARTESIAN, "Due NW");
|
||||
c3.CourseAndDistance( cur_lon, cur_lat, cur_alt, &course, &distance );
|
||||
cout << "Course to " << c3.get_id() << " is " << course << endl;
|
||||
cout << "Distance to " << c3.get_id() << " is " << distance << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
includedir = @includedir@/scene
|
||||
|
||||
SUBDIRS = material model sky tgdb util
|
||||
SUBDIRS = bvh material model sky tgdb util
|
||||
|
||||
# lib_LIBRARIES = libsgscene.a
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef BVHBoundingBoxVisitor_hxx
|
||||
#define BVHBoundingBoxVisitor_hxx
|
||||
|
||||
#include <simgear/math/SGGeometry.hxx>
|
||||
|
||||
#include "BVHVisitor.hxx"
|
||||
#include "BVHNode.hxx"
|
||||
#include "BVHGroup.hxx"
|
||||
#include "BVHTransform.hxx"
|
||||
#include "BVHMotionTransform.hxx"
|
||||
#include "BVHLineGeometry.hxx"
|
||||
|
||||
#include "BVHStaticData.hxx"
|
||||
|
||||
#include "BVHStaticNode.hxx"
|
||||
#include "BVHStaticTriangle.hxx"
|
||||
#include "BVHStaticBinary.hxx"
|
||||
#include "BVHStaticGeometry.hxx"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
class BVHBoundingBoxVisitor : public BVHVisitor {
|
||||
public:
|
||||
virtual ~BVHBoundingBoxVisitor() {}
|
||||
|
||||
void clear()
|
||||
{ _box.clear(); }
|
||||
|
||||
virtual void apply(BVHGroup& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
virtual void apply(BVHTransform& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
virtual void apply(BVHMotionTransform& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
virtual void apply(BVHLineGeometry& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
virtual void apply(BVHStaticGeometry& node)
|
||||
{ expandBy(node.getBoundingSphere()); }
|
||||
|
||||
virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
|
||||
{ expandBy(node.getBoundingBox()); }
|
||||
virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
|
||||
{ expandBy(node.computeBoundingBox(data)); }
|
||||
|
||||
const SGBoxf& getBox() const
|
||||
{ return _box; }
|
||||
|
||||
private:
|
||||
void expandBy(const SGSphered& sphere)
|
||||
{
|
||||
SGVec3f v0(sphere.getCenter() - sphere.getRadius()*SGVec3d(1, 1, 1));
|
||||
SGVec3f v1(sphere.getCenter() + sphere.getRadius()*SGVec3d(1, 1, 1));
|
||||
_box.expandBy(SGBoxf(v0, v1));
|
||||
}
|
||||
void expandBy(const SGBoxf& box)
|
||||
{ _box.expandBy(box); }
|
||||
|
||||
SGBoxf _box;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,210 @@
|
||||
// Copyright (C) 2008 - 2009 Mathias Froehlich - Mathias.Froehlich@web.de
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef BVHDebugCollectVisitor_hxx
|
||||
#define BVHDebugCollectVisitor_hxx
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/PolygonOffset>
|
||||
#include <osg/PrimitiveSet>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/Shape>
|
||||
#include <osg/Depth>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/StateSet>
|
||||
|
||||
#include <simgear/math/SGGeometry.hxx>
|
||||
|
||||
#include "BVHVisitor.hxx"
|
||||
#include "BVHNode.hxx"
|
||||
#include "BVHGroup.hxx"
|
||||
#include "BVHTransform.hxx"
|
||||
#include "BVHMotionTransform.hxx"
|
||||
#include "BVHStaticGeometry.hxx"
|
||||
|
||||
#include "BVHStaticData.hxx"
|
||||
|
||||
#include "BVHStaticNode.hxx"
|
||||
#include "BVHStaticTriangle.hxx"
|
||||
#include "BVHStaticBinary.hxx"
|
||||
|
||||
#include "BVHBoundingBoxVisitor.hxx"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
class BVHNode;
|
||||
class BVHStaticNode;
|
||||
|
||||
class BVHDebugCollectVisitor : public BVHVisitor {
|
||||
public:
|
||||
BVHDebugCollectVisitor(const double& time, unsigned level = ~0u) :
|
||||
_group(new osg::Group),
|
||||
_time(time),
|
||||
_level(level),
|
||||
_currentLevel(0)
|
||||
{
|
||||
osg::StateSet* stateSet = _group->getOrCreateStateSet();
|
||||
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
stateSet->setAttribute(new osg::Depth(osg::Depth::LESS, 0, 1, false));
|
||||
osg::BlendFunc *blendFunc;
|
||||
blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA,
|
||||
osg::BlendFunc::DST_ALPHA);
|
||||
stateSet->setAttributeAndModes(blendFunc);
|
||||
osg::PolygonOffset* polygonOffset = new osg::PolygonOffset(-1, -1);
|
||||
stateSet->setAttributeAndModes(polygonOffset);
|
||||
}
|
||||
virtual ~BVHDebugCollectVisitor()
|
||||
{ }
|
||||
|
||||
virtual void apply(BVHGroup& node)
|
||||
{
|
||||
addNodeSphere(node);
|
||||
++_currentLevel;
|
||||
node.traverse(*this);
|
||||
--_currentLevel;
|
||||
}
|
||||
virtual void apply(BVHTransform& node)
|
||||
{
|
||||
addNodeSphere(node);
|
||||
osg::ref_ptr<osg::Group> oldGroup = _group;
|
||||
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
|
||||
transform->setMatrix(osg::Matrix(node.getToWorldTransform().data()));
|
||||
_group = transform;
|
||||
++_currentLevel;
|
||||
node.traverse(*this);
|
||||
--_currentLevel;
|
||||
_group = oldGroup;
|
||||
if (transform->getNumChildren())
|
||||
_group->addChild(transform.get());
|
||||
}
|
||||
virtual void apply(BVHMotionTransform& node)
|
||||
{
|
||||
addNodeSphere(node);
|
||||
osg::ref_ptr<osg::Group> oldGroup = _group;
|
||||
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
|
||||
transform->setMatrix(osg::Matrix(node.getToWorldTransform(_time).data()));
|
||||
_group = transform;
|
||||
++_currentLevel;
|
||||
node.traverse(*this);
|
||||
--_currentLevel;
|
||||
_group = oldGroup;
|
||||
if (transform->getNumChildren())
|
||||
_group->addChild(transform.get());
|
||||
}
|
||||
virtual void apply(BVHLineGeometry&)
|
||||
{
|
||||
}
|
||||
virtual void apply(BVHStaticGeometry& node)
|
||||
{
|
||||
addNodeSphere(node);
|
||||
++_currentLevel;
|
||||
node.traverse(*this);
|
||||
--_currentLevel;
|
||||
}
|
||||
|
||||
virtual void apply(const BVHStaticBinary& node, const BVHStaticData& data)
|
||||
{
|
||||
addNodeBox(node, data);
|
||||
++_currentLevel;
|
||||
node.traverse(*this, data);
|
||||
--_currentLevel;
|
||||
}
|
||||
virtual void apply(const BVHStaticTriangle& node, const BVHStaticData& data)
|
||||
{
|
||||
addNodeBox(node, data);
|
||||
addTriangle(node.getTriangle(data), osg::Vec4(0.5, 0, 0.5, 0.2));
|
||||
}
|
||||
|
||||
osg::Node* getNode() const { return _group.get(); }
|
||||
|
||||
static unsigned allLevels() { return ~0u; }
|
||||
static unsigned triangles() { return ~0u - 1; }
|
||||
|
||||
private:
|
||||
void addTriangle(const SGTrianglef& triangle, const osg::Vec4& color)
|
||||
{
|
||||
if (_level != triangles())
|
||||
return;
|
||||
|
||||
osg::Geometry* geometry = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
||||
vertices->push_back(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()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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 BVHStaticLeaf_hxx
|
||||
#define BVHStaticLeaf_hxx
|
||||
|
||||
#include <simgear/math/SGGeometry.hxx>
|
||||
#include "BVHStaticNode.hxx"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
class BVHStaticLeaf : public BVHStaticNode {
|
||||
public:
|
||||
virtual ~BVHStaticLeaf();
|
||||
|
||||
virtual void accept(BVHVisitor& visitor, const BVHStaticData& data) const = 0;
|
||||
|
||||
virtual SGBoxf computeBoundingBox(const BVHStaticData&) const = 0;
|
||||
virtual SGVec3f computeCenter(const BVHStaticData&) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
// 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 "BVHStaticNode.hxx"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
BVHStaticNode::~BVHStaticNode()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user