Compare commits
439
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11479cd8c3 | ||
|
|
176e760de1 | ||
|
|
430c60ed1a | ||
|
|
dfea3623f6 | ||
|
|
b38783e4cb | ||
|
|
9382a4c21b | ||
|
|
3cd4c5566f | ||
|
|
601c0977df | ||
|
|
c56f036bab | ||
|
|
44dd50c0ef | ||
|
|
56919ae45f | ||
|
|
578af00b0d | ||
|
|
d6c0bf69b6 | ||
|
|
e8884b4ec0 | ||
|
|
5e79609955 | ||
|
|
4950c96f1c | ||
|
|
51b0cf535e | ||
|
|
4cc17a7f6e | ||
|
|
dca07c5634 | ||
|
|
fd42294faf | ||
|
|
c1246e8c4e | ||
|
|
59fc902cfb | ||
|
|
1fe9755d01 | ||
|
|
1da09a4706 | ||
|
|
f3c591469b | ||
|
|
b1200f9f59 | ||
|
|
47617d6c04 | ||
|
|
4794ab6095 | ||
|
|
bc85767f19 | ||
|
|
e37c218c2a | ||
|
|
a0aaa23904 | ||
|
|
27a6c72091 | ||
|
|
2dcc66f03e | ||
|
|
d70a05a088 | ||
|
|
c2317edf8a | ||
|
|
cb7ac404d9 | ||
|
|
5abc6c995f | ||
|
|
0f21c39e49 | ||
|
|
f6513127ce | ||
|
|
ddd72b2b37 | ||
|
|
7f5df1fb66 | ||
|
|
2e71b64de1 | ||
|
|
45f1f9263f | ||
|
|
878288f06a | ||
|
|
406cdf8d16 | ||
|
|
5b28b024ae | ||
|
|
7c693d8107 | ||
|
|
b8a6d1ac4d | ||
|
|
40533f50df | ||
|
|
539ced191b | ||
|
|
1a400b890b | ||
|
|
ebe5a5579c | ||
|
|
afb18ca75b | ||
|
|
01c62932bd | ||
|
|
6cd8db7b28 | ||
|
|
bb46d91bc6 | ||
|
|
3cd5322496 | ||
|
|
cadecdcab7 | ||
|
|
cd4030b7db | ||
|
|
0a2264cad4 | ||
|
|
bb2a02daa8 | ||
|
|
5991195062 | ||
|
|
54c4055af3 | ||
|
|
cb07210bc7 | ||
|
|
3e40d624a8 | ||
|
|
63ce675914 | ||
|
|
14e5e87a4d | ||
|
|
e7e81c6639 | ||
|
|
23d0601d82 | ||
|
|
6db9138eeb | ||
|
|
6a7c200002 | ||
|
|
e3f70b7125 | ||
|
|
a25e859fa7 | ||
|
|
5b2af1f6b3 | ||
|
|
59df72c4b0 | ||
|
|
4e2eb2f24c | ||
|
|
b905f4b8aa | ||
|
|
fefe87ed1e | ||
|
|
b66905c2f6 | ||
|
|
39472e4d81 | ||
|
|
85fba1325a | ||
|
|
0f39f05fa1 | ||
|
|
8d551c2664 | ||
|
|
346a22f684 | ||
|
|
b1571e4437 | ||
|
|
5ac2abe3ab | ||
|
|
5b15426cc6 | ||
|
|
1ac944b7c1 | ||
|
|
fd90dbb123 | ||
|
|
6ccad91537 | ||
|
|
c89db53ebf | ||
|
|
4ffd70a42a | ||
|
|
bbeb48a60d | ||
|
|
aefe9bc116 | ||
|
|
bcb95f647d | ||
|
|
145a7fa146 | ||
|
|
06f0b6030a | ||
|
|
191ee3a0ed | ||
|
|
f6358694ae | ||
|
|
af14d65a98 | ||
|
|
9fe75dc521 | ||
|
|
0051bea034 | ||
|
|
76c79dba8e | ||
|
|
84dc82506a | ||
|
|
ae1625734c | ||
|
|
e2ce4c0fa9 | ||
|
|
a06a15e769 | ||
|
|
7c5de29b61 | ||
|
|
5f9befebae | ||
|
|
6a7b885891 | ||
|
|
cd8e7bbdca | ||
|
|
5d731ad8c3 | ||
|
|
7964270929 | ||
|
|
ea513d392e | ||
|
|
feba9024eb | ||
|
|
b3e16ce8e0 | ||
|
|
31dd77c694 | ||
|
|
ae58f89fbf | ||
|
|
b3bc36b253 | ||
|
|
7287509fef | ||
|
|
b1c49045a8 | ||
|
|
0d5634475c | ||
|
|
e6bfe7d40c | ||
|
|
811cd0653f | ||
|
|
e2b8a21ff5 | ||
|
|
24c7941f65 | ||
|
|
600a9ee4c5 | ||
|
|
fdfdfedf01 | ||
|
|
a67688322d | ||
|
|
6fe057e277 | ||
|
|
f23e8bfb02 | ||
|
|
eab9da98f2 | ||
|
|
f161992836 | ||
|
|
40e13b91fe | ||
|
|
af6824605b | ||
|
|
babf58f8d2 | ||
|
|
968f5d7693 | ||
|
|
4cc6bd69ae | ||
|
|
199437e859 | ||
|
|
e5fac0a01d | ||
|
|
5d14b84969 | ||
|
|
bcccd06cee | ||
|
|
6b0ab9a49a | ||
|
|
023002ae73 | ||
|
|
579d384c04 | ||
|
|
e2e1524454 | ||
|
|
4a5853c1c2 | ||
|
|
64756d14d0 | ||
|
|
bac2ef601d | ||
|
|
cf3bab89f9 | ||
|
|
dfe41ad984 | ||
|
|
b784bebaa9 | ||
|
|
bcf727cf58 | ||
|
|
ecd0a53412 | ||
|
|
3456434e37 | ||
|
|
454c5b1ed2 | ||
|
|
dc2c437a1a | ||
|
|
819d3f5ded | ||
|
|
4f802689f2 | ||
|
|
9cbbe55598 | ||
|
|
7e2dafdcb8 | ||
|
|
c7873d68f7 | ||
|
|
939ec526a8 | ||
|
|
b20a635db0 | ||
|
|
a656bee0df | ||
|
|
42f07e3f14 | ||
|
|
5803b05bd5 | ||
|
|
ccf0ba50c4 | ||
|
|
f3bc977d32 | ||
|
|
80609e0816 | ||
|
|
795d481ca6 | ||
|
|
1b936b9af8 | ||
|
|
f141cc28b0 | ||
|
|
4cb64b58be | ||
|
|
028af34d3d | ||
|
|
ce54997be5 | ||
|
|
3d213fa713 | ||
|
|
e71f3790ce | ||
|
|
67b9cba4d3 | ||
|
|
78a471f684 | ||
|
|
d4289c5d54 | ||
|
|
0c17c5440a | ||
|
|
c4116da564 | ||
|
|
d0821953bb | ||
|
|
e782adef94 | ||
|
|
d3572c2562 | ||
|
|
1f3838b155 | ||
|
|
6aa459073e | ||
|
|
0932c33185 | ||
|
|
5e542aa841 | ||
|
|
6d53abd5af | ||
|
|
3ea58bf8db | ||
|
|
71a4c2c3d2 | ||
|
|
a3e391a523 | ||
|
|
9cb15b302c | ||
|
|
15c1a28d37 | ||
|
|
d3a500e54e | ||
|
|
a0a5eb8aef | ||
|
|
a92955eade | ||
|
|
f043f3d4f9 | ||
|
|
992a057a1b | ||
|
|
07da1e7e1a | ||
|
|
2c07222ef6 | ||
|
|
918e315d47 | ||
|
|
c824731bc6 | ||
|
|
0c39caa622 | ||
|
|
1f1e28baf8 | ||
|
|
0c303389d6 | ||
|
|
01a896ef5b | ||
|
|
0e5e760135 | ||
|
|
7e7d877874 | ||
|
|
57ccb6fd6b | ||
|
|
efa2876e29 | ||
|
|
59ef7d8fd1 | ||
|
|
1f308c9ec3 | ||
|
|
4943d3aa53 | ||
|
|
828d561113 | ||
|
|
fcf72a7123 | ||
|
|
d3f5bc6e2d | ||
|
|
f525a05be8 | ||
|
|
fc7ec4299e | ||
|
|
21d053b1b6 | ||
|
|
68e64a5aa7 | ||
|
|
8e718fe288 | ||
|
|
efec9070e1 | ||
|
|
e3646d4d4a | ||
|
|
4219f16f61 | ||
|
|
c3b1802e95 | ||
|
|
40fe078021 | ||
|
|
a5a6600e74 | ||
|
|
03b9303f22 | ||
|
|
b5a59ea6f9 | ||
|
|
c6b2124129 | ||
|
|
d320a6facb | ||
|
|
0793c2cb8c | ||
|
|
d14755abb8 | ||
|
|
abd4aa2e6b | ||
|
|
58417e78e5 | ||
|
|
390eb1c6e9 | ||
|
|
d4c6530a72 | ||
|
|
ff17b44a41 | ||
|
|
5bd2d47571 | ||
|
|
f8e475cd34 | ||
|
|
a05e063949 | ||
|
|
eb06a90109 | ||
|
|
e2f6632fee | ||
|
|
5c5c583dcc | ||
|
|
0d8d5c02d0 | ||
|
|
382e0c6ad2 | ||
|
|
a8d1c44408 | ||
|
|
78b4318c34 | ||
|
|
b47031a099 | ||
|
|
0f7b65a921 | ||
|
|
33f7903aeb | ||
|
|
f3c2740917 | ||
|
|
09a57c7a52 | ||
|
|
9068f0606e | ||
|
|
c577b7e369 | ||
|
|
5850464ba7 | ||
|
|
50e240d5e4 | ||
|
|
75c2a45b25 | ||
|
|
c958d63897 | ||
|
|
b633b8d0d3 | ||
|
|
76948416a9 | ||
|
|
f4a527c57c | ||
|
|
c491baff0e | ||
|
|
6d05fc6f57 | ||
|
|
ca53add820 | ||
|
|
6fe3099ab4 | ||
|
|
a34eceb327 | ||
|
|
c9042c3186 | ||
|
|
b46fe0d51c | ||
|
|
6d1d3173fe | ||
|
|
030d044d03 | ||
|
|
29fb8e0f74 | ||
|
|
6e326976d5 | ||
|
|
03a7d72a62 | ||
|
|
f913febd71 | ||
|
|
daa0fbdc6b | ||
|
|
d4c52b599d | ||
|
|
ec88373eb7 | ||
|
|
4286cafdeb | ||
|
|
3880d8e2f2 | ||
|
|
671c84ad44 | ||
|
|
a0d687bb24 | ||
|
|
704385ff0a | ||
|
|
81a657edec | ||
|
|
9d0bad29c0 | ||
|
|
2fb8e32104 | ||
|
|
c522e499b2 | ||
|
|
4700955480 | ||
|
|
2c66081fa4 | ||
|
|
855e88da43 | ||
|
|
ad302db9a8 | ||
|
|
bfa5fff500 | ||
|
|
01c64fd554 | ||
|
|
13a2b92a32 | ||
|
|
29e79f8f61 | ||
|
|
8f7527ede0 | ||
|
|
7cd149a4d8 | ||
|
|
e45912fd8a | ||
|
|
56c4ba67c6 | ||
|
|
7e7ce2f38e | ||
|
|
7dc9eba2d0 | ||
|
|
f91d96b51a | ||
|
|
bc19609147 | ||
|
|
1ccaf3a0bd | ||
|
|
03bfd829da | ||
|
|
e1f7a1e0a0 | ||
|
|
ceeac0ecf0 | ||
|
|
c9d0eac739 | ||
|
|
8f24d924ee | ||
|
|
8537cc9edf | ||
|
|
58f3985567 | ||
|
|
872db67f21 | ||
|
|
006f90997a | ||
|
|
26b4776394 | ||
|
|
66c64459e6 | ||
|
|
dc8657f57f | ||
|
|
9d647b90e0 | ||
|
|
f5730c950b | ||
|
|
15d37daebd | ||
|
|
795c9876af | ||
|
|
45f653167d | ||
|
|
403d9b6ac1 | ||
|
|
722af5f659 | ||
|
|
471b9f02ec | ||
|
|
fd294b6f98 | ||
|
|
88baaa72be | ||
|
|
61084cf1ba | ||
|
|
5b63f0755a | ||
|
|
9eb5cf6c98 | ||
|
|
679db5a22b | ||
|
|
0e35168bdb | ||
|
|
035dcc7ab7 | ||
|
|
252deed5b9 | ||
|
|
c2c4cad753 | ||
|
|
42e76477cf | ||
|
|
1eade74e5a | ||
|
|
f1f0fa0aa9 | ||
|
|
deef158822 | ||
|
|
fef2006663 | ||
|
|
5c97fd576a | ||
|
|
c4eb6b7b65 | ||
|
|
31324761cc | ||
|
|
e495f03ee9 | ||
|
|
f5769627e4 | ||
|
|
06ad73f85b | ||
|
|
fa20363853 | ||
|
|
2564432e71 | ||
|
|
addf47600d | ||
|
|
7f534a7966 | ||
|
|
eabffece1f | ||
|
|
afed842ad1 | ||
|
|
c46cfb5d47 | ||
|
|
34fe42bbd9 | ||
|
|
0c1d96b749 | ||
|
|
9b67f52d56 | ||
|
|
d37907d35d | ||
|
|
fee8d0cf78 | ||
|
|
f5f9c6b81f | ||
|
|
4e3460a34b | ||
|
|
8545b6ce6b | ||
|
|
e417903c23 | ||
|
|
81eae3fa48 | ||
|
|
90c58087e8 | ||
|
|
19bc1e6313 | ||
|
|
4a4e8c87b8 | ||
|
|
f04e559dc2 | ||
|
|
8e5e657344 | ||
|
|
a4f1f62068 | ||
|
|
a3e279f06f | ||
|
|
d11954e80c | ||
|
|
812170ebce | ||
|
|
fdd3c77298 | ||
|
|
342de209a2 | ||
|
|
caeb32488e | ||
|
|
ff7e70f4d5 | ||
|
|
950f51909c | ||
|
|
f86e6d344c | ||
|
|
08581282dd | ||
|
|
e1e47e76ec | ||
|
|
3ff059848c | ||
|
|
22c7df5936 | ||
|
|
81a44d1340 | ||
|
|
2c089e6166 | ||
|
|
589dae7b0c | ||
|
|
3ff13189aa | ||
|
|
7151c3fac1 | ||
|
|
3e023b77dd | ||
|
|
e3fc89890c | ||
|
|
ce2a6cfe5c | ||
|
|
31d9eaf54c | ||
|
|
781c445d14 | ||
|
|
26a416399f | ||
|
|
f7dc7f039e | ||
|
|
3c74fea087 | ||
|
|
be0635bfd3 | ||
|
|
6723ef95c2 | ||
|
|
1a8fd62680 | ||
|
|
8b57ed46b1 | ||
|
|
25c08e56c2 | ||
|
|
0f148b6ab6 | ||
|
|
47575fe357 | ||
|
|
7c14453b5a | ||
|
|
a47d5536fa | ||
|
|
db8f7f21e8 | ||
|
|
3c312c55f1 | ||
|
|
2d11419cba | ||
|
|
07a4508944 | ||
|
|
62913739bb | ||
|
|
55e9d8d944 | ||
|
|
a9439d58c7 | ||
|
|
800ad40c4c | ||
|
|
62864637a3 | ||
|
|
4d4ac7ea24 | ||
|
|
119651482d | ||
|
|
ecf0a1a736 | ||
|
|
94942d1ac4 | ||
|
|
b0a5b54949 | ||
|
|
ac57eab8ac | ||
|
|
74a4144193 | ||
|
|
5c44cb0f01 | ||
|
|
c044d711ef | ||
|
|
f2132f6a7d | ||
|
|
69871b15ff | ||
|
|
f4ec02a592 | ||
|
|
53f7743678 | ||
|
|
15893bc558 | ||
|
|
73b974f1b5 | ||
|
|
0e7bdc208b | ||
|
|
e0a07b7a92 | ||
|
|
4da58e8846 | ||
|
|
966b9e5c2b | ||
|
|
1625192c81 | ||
|
|
c5e8c6603c | ||
|
|
37e541d326 | ||
|
|
862a827fe6 | ||
|
|
b96c5c9e4b |
@@ -22,7 +22,7 @@ PROJECT_NAME = SimGear
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 1.99.5
|
||||
PROJECT_NUMBER = 1.9.0
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
Version 1.99.5
|
||||
* October 30, 2008 (sourcecode snapshot release)
|
||||
Version 1.9.0
|
||||
* Thu Dec 18 15:12:15 CST 2008
|
||||
|
||||
|
||||
Version 1.8.6
|
||||
* Mon Dec 1 14:02:47 CST 2008
|
||||
|
||||
|
||||
Version 1.8.5
|
||||
* October 30, 2008 (source code snapshot release)
|
||||
|
||||
|
||||
New in 0.3.10
|
||||
|
||||
+5
-2
@@ -3,16 +3,19 @@
|
||||
You *must* have OpenSceneGraph (OSG) installed to build this version of
|
||||
FlightGear.
|
||||
|
||||
Notice that FlightGear 1.9.0 requires at least version 2.7.8. Using earlier
|
||||
versions of OSG will yield serious rendering bugs.
|
||||
|
||||
You can get the latest version of OSG from:
|
||||
|
||||
http://www.openscenegraph.org/
|
||||
|
||||
Build notes:
|
||||
|
||||
Unzip the file OpenSceneGraph-2.4.zip and install using the following
|
||||
Unzip the file OpenSceneGraph-x.x.zip and install using the following
|
||||
commands:
|
||||
|
||||
unzip OpenSceneGraph-2.4
|
||||
unzip OpenSceneGraph-x.x
|
||||
cd OpenSceneGraph
|
||||
ccmake .
|
||||
|
||||
|
||||
+10
-10
@@ -3,27 +3,27 @@
|
||||
You *must* have the development components of OpenAL installed on your system
|
||||
to build FlightGear!" You can get a copy here:
|
||||
|
||||
http://www.openal.org
|
||||
http://connect.creativelabs.com/openal/default.aspx
|
||||
|
||||
Build notes:
|
||||
|
||||
You can download a versioned release of the openal library from
|
||||
http://www.openal.org/downloads.html. Download the openal source,
|
||||
release 0.0.8 (dated February 11, 2006) and run:
|
||||
tar xzvf openal-0.0.8.tar.gz
|
||||
cd openal-0.0.8
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
tar xjvf openal-soft-1.5.304.tar.bz2
|
||||
cd openal-soft-1.5.304/
|
||||
ccmake .
|
||||
|
||||
[ While running ccmake: press 'c' to configure, press 'c' once more, and
|
||||
then press 'g' to generate and exit ]
|
||||
|
||||
|
||||
The alut library is also required, but comes separately in the package
|
||||
freelut-1.1.0.tar.gz. This package can be downloaded from the same page
|
||||
(http://www.openal.org/downloads.html). Download and run:
|
||||
(http://connect.creativelabs.com/openal/default.aspx). Download and run:
|
||||
tar xzvf freelut-1.1.0.tar.gz
|
||||
cd freelut-1.1.0
|
||||
cd freealut-1.1.0
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
|
||||
Alternatively, you can use the CVS version (follow the instructions at
|
||||
the OpenAL web site) and build/install that one.
|
||||
|
||||
-2720
File diff suppressed because it is too large
Load Diff
-29
@@ -1,29 +0,0 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "SimGear"=".\SimGear.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
+224
@@ -460,3 +460,227 @@ pushdef([AC_PROG_INSTALL],
|
||||
INSTALL_PROGRAM='${INSTALL} $(INSTALL_STRIP_FLAG)'
|
||||
INSTALL_SCRIPT='${INSTALL}'
|
||||
])dnl
|
||||
|
||||
# ===========================================================================
|
||||
# http://autoconf-archive.cryp.to/ax_boost_base.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_BOOST_BASE([MINIMUM-VERSION])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Test for the Boost C++ libraries of a particular version (or newer)
|
||||
#
|
||||
# If no path to the installed boost library is given the macro searchs
|
||||
# under /usr, /usr/local, /opt and /opt/local and evaluates the
|
||||
# $BOOST_ROOT environment variable. Further documentation is available at
|
||||
# <http://randspringer.de/boost/index.html>.
|
||||
#
|
||||
# This macro calls:
|
||||
#
|
||||
# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
|
||||
#
|
||||
# And sets:
|
||||
#
|
||||
# HAVE_BOOST
|
||||
#
|
||||
# LAST MODIFICATION
|
||||
#
|
||||
# 2008-04-12
|
||||
#
|
||||
# COPYLEFT
|
||||
#
|
||||
# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved.
|
||||
|
||||
AC_DEFUN([AX_BOOST_BASE],
|
||||
[
|
||||
AC_ARG_WITH([boost],
|
||||
AS_HELP_STRING([--with-boost@<:@=DIR@:>@], [use boost (default is yes) - it is possible to specify the root directory for boost (optional)]),
|
||||
[
|
||||
if test "$withval" = "no"; then
|
||||
want_boost="no"
|
||||
elif test "$withval" = "yes"; then
|
||||
want_boost="yes"
|
||||
ac_boost_path=""
|
||||
else
|
||||
want_boost="yes"
|
||||
ac_boost_path="$withval"
|
||||
fi
|
||||
],
|
||||
[want_boost="yes"])
|
||||
|
||||
|
||||
AC_ARG_WITH([boost-libdir],
|
||||
AS_HELP_STRING([--with-boost-libdir=LIB_DIR],
|
||||
[Force given directory for boost libraries. Note that this will overwrite library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]),
|
||||
[
|
||||
if test -d $withval
|
||||
then
|
||||
ac_boost_lib_path="$withval"
|
||||
else
|
||||
AC_MSG_ERROR(--with-boost-libdir expected directory name)
|
||||
fi
|
||||
],
|
||||
[ac_boost_lib_path=""]
|
||||
)
|
||||
|
||||
if test "x$want_boost" = "xyes"; then
|
||||
boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
|
||||
boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
|
||||
boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'`
|
||||
boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
|
||||
boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
|
||||
if test "x$boost_lib_version_req_sub_minor" = "x" ; then
|
||||
boost_lib_version_req_sub_minor="0"
|
||||
fi
|
||||
WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
|
||||
AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
|
||||
succeeded=no
|
||||
|
||||
dnl first we check the system location for boost libraries
|
||||
dnl this location ist chosen if boost libraries are installed with the --layout=system option
|
||||
dnl or if you install boost with RPM
|
||||
if test "$ac_boost_path" != ""; then
|
||||
BOOST_LDFLAGS="-L$ac_boost_path/lib"
|
||||
BOOST_CPPFLAGS="-I$ac_boost_path/include"
|
||||
else
|
||||
for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
|
||||
if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then
|
||||
BOOST_LDFLAGS="-L$ac_boost_path_tmp/lib"
|
||||
BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
dnl overwrite ld flags if we have required special directory with
|
||||
dnl --with-boost-libdir parameter
|
||||
if test "$ac_boost_lib_path" != ""; then
|
||||
BOOST_LDFLAGS="-L$ac_boost_lib_path"
|
||||
fi
|
||||
|
||||
CPPFLAGS_SAVED="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
||||
export CPPFLAGS
|
||||
|
||||
LDFLAGS_SAVED="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
|
||||
export LDFLAGS
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
@%:@include <boost/version.hpp>
|
||||
]], [[
|
||||
#if BOOST_VERSION >= $WANT_BOOST_VERSION
|
||||
// Everything is okay
|
||||
#else
|
||||
# error Boost version is too old
|
||||
#endif
|
||||
]])],[
|
||||
AC_MSG_RESULT(yes)
|
||||
succeeded=yes
|
||||
found_system=yes
|
||||
],[
|
||||
])
|
||||
AC_LANG_POP([C++])
|
||||
|
||||
|
||||
|
||||
dnl if we found no boost with system layout we search for boost libraries
|
||||
dnl built and installed without the --layout=system option or for a staged(not installed) version
|
||||
if test "x$succeeded" != "xyes"; then
|
||||
_version=0
|
||||
if test "$ac_boost_path" != ""; then
|
||||
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
|
||||
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
|
||||
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
|
||||
V_CHECK=`expr $_version_tmp \> $_version`
|
||||
if test "$V_CHECK" = "1" ; then
|
||||
_version=$_version_tmp
|
||||
fi
|
||||
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
|
||||
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
|
||||
done
|
||||
fi
|
||||
else
|
||||
for ac_boost_path in /usr /usr/local /opt /opt/local ; do
|
||||
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
|
||||
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
|
||||
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
|
||||
V_CHECK=`expr $_version_tmp \> $_version`
|
||||
if test "$V_CHECK" = "1" ; then
|
||||
_version=$_version_tmp
|
||||
best_path=$ac_boost_path
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
|
||||
BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
|
||||
if test "$ac_boost_lib_path" = ""
|
||||
then
|
||||
BOOST_LDFLAGS="-L$best_path/lib"
|
||||
fi
|
||||
|
||||
if test "x$BOOST_ROOT" != "x"; then
|
||||
if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/lib" && test -r "$BOOST_ROOT/stage/lib"; then
|
||||
version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'`
|
||||
stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`
|
||||
stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
|
||||
V_CHECK=`expr $stage_version_shorten \>\= $_version`
|
||||
if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then
|
||||
AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
|
||||
BOOST_CPPFLAGS="-I$BOOST_ROOT"
|
||||
BOOST_LDFLAGS="-L$BOOST_ROOT/stage/lib"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
||||
export CPPFLAGS
|
||||
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
|
||||
export LDFLAGS
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
@%:@include <boost/version.hpp>
|
||||
]], [[
|
||||
#if BOOST_VERSION >= $WANT_BOOST_VERSION
|
||||
// Everything is okay
|
||||
#else
|
||||
# error Boost version is too old
|
||||
#endif
|
||||
]])],[
|
||||
AC_MSG_RESULT(yes)
|
||||
succeeded=yes
|
||||
found_system=yes
|
||||
],[
|
||||
])
|
||||
AC_LANG_POP([C++])
|
||||
fi
|
||||
|
||||
if test "$succeeded" != "yes" ; then
|
||||
if test "$_version" = "0" ; then
|
||||
AC_MSG_ERROR([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
|
||||
else
|
||||
AC_MSG_ERROR([Your boost libraries seems to old (version $_version).])
|
||||
fi
|
||||
else
|
||||
AC_SUBST(BOOST_CPPFLAGS)
|
||||
AC_SUBST(BOOST_LDFLAGS)
|
||||
AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS_SAVED"
|
||||
LDFLAGS="$LDFLAGS_SAVED"
|
||||
fi
|
||||
|
||||
])
|
||||
|
||||
+133
-5
@@ -8,7 +8,7 @@ dnl Require at least automake 2.52
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
dnl Initialize the automake stuff
|
||||
AM_INIT_AUTOMAKE(SimGear, 1.99.5-rc2)
|
||||
AM_INIT_AUTOMAKE(SimGear, 1.9.1)
|
||||
|
||||
dnl Specify KAI C++ compiler and flags.
|
||||
dnl Borrowed with slight modification from blitz distribution.
|
||||
@@ -37,6 +37,11 @@ AC_PROG_CXX
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AX_BOOST_BASE([1.37.0])
|
||||
|
||||
if test "x$BOOST_CPPFLAGS" != "x-I/usr/include" ; then
|
||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
||||
fi
|
||||
|
||||
dnl set the $host variable based on local machine/os
|
||||
AC_CANONICAL_HOST
|
||||
@@ -121,6 +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])
|
||||
|
||||
@@ -129,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*)
|
||||
@@ -198,6 +224,7 @@ LIBS=""
|
||||
|
||||
dnl check for some default libraries
|
||||
AC_SEARCH_LIBS(cos, m)
|
||||
AC_SEARCH_LIBS(clock_gettime, rt)
|
||||
|
||||
base_LIBS="$LIBS"
|
||||
|
||||
@@ -287,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
|
||||
|
||||
;;
|
||||
|
||||
*)
|
||||
@@ -346,9 +418,23 @@ AM_CONDITIONAL(EXTGL_NEEDED, test "x$ac_cv_header_windows_h" = "xyes")
|
||||
# The following are C++ items that need to be tested for with the c++
|
||||
# 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
|
||||
@@ -368,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;
|
||||
}
|
||||
@@ -386,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!"
|
||||
@@ -396,6 +512,17 @@ if test "x$ac_cv_header_osg_Version" != "xyes"; then
|
||||
echo
|
||||
echo "configure aborted."
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADER(boost/version.hpp)
|
||||
if test "x$ac_cv_header_boost_version_hpp" != "xyes"; then
|
||||
echo
|
||||
echo "You *must* have the Boost library installed on your system"
|
||||
echo "to build this version of SimGear!"
|
||||
echo
|
||||
echo "configure aborted."
|
||||
exit
|
||||
fi
|
||||
|
||||
AC_LANG_POP
|
||||
@@ -465,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""
|
||||
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""
|
||||
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
+2001
-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;
|
||||
|
||||
+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
|
||||
|
||||
+28
-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,27 @@ public:
|
||||
/// Set the geodetic elevation from the argument given in feet
|
||||
void setElevationFt(double elevation);
|
||||
|
||||
#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 +200,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)
|
||||
|
||||
@@ -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,71 @@
|
||||
#include "AtomicChangeListener.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
MultiChangeListener::MultiChangeListener()
|
||||
{
|
||||
}
|
||||
|
||||
void MultiChangeListener::valueChanged(SGPropertyNode* node)
|
||||
{
|
||||
valueChangedImplementation();
|
||||
}
|
||||
|
||||
void MultiChangeListener::valueChangedImplementation()
|
||||
{
|
||||
}
|
||||
|
||||
AtomicChangeListener::AtomicChangeListener(std::vector<SGPropertyNode*>& nodes)
|
||||
: _dirty(false), _valid(true)
|
||||
{
|
||||
listenToProperties(nodes.begin(), nodes.end());
|
||||
}
|
||||
|
||||
void AtomicChangeListener::unregister_property(SGPropertyNode* node)
|
||||
{
|
||||
_valid = false;
|
||||
// not necessary, but good hygine
|
||||
vector<SGPropertyNode*>::iterator itr
|
||||
= find(_watched.begin(), _watched.end(), node);
|
||||
if (itr != _watched.end())
|
||||
*itr = 0;
|
||||
MultiChangeListener::unregister_property(node);
|
||||
}
|
||||
|
||||
void AtomicChangeListener::fireChangeListeners()
|
||||
{
|
||||
vector<SGSharedPtr<AtomicChangeListener> >& listeners
|
||||
= ListenerListSingleton::instance()->listeners;
|
||||
for (vector<SGSharedPtr<AtomicChangeListener> >::iterator itr = listeners.begin(),
|
||||
end = listeners.end();
|
||||
itr != end;
|
||||
++itr) {
|
||||
(*itr)->valuesChanged();
|
||||
(*itr)->_dirty = false;
|
||||
}
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
void AtomicChangeListener::valueChangedImplementation()
|
||||
{
|
||||
if (!_dirty) {
|
||||
_dirty = true;
|
||||
if (_valid)
|
||||
ListenerListSingleton::instance()->listeners.push_back(this);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomicChangeListener::valuesChanged()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
#ifndef SIMGEAR_ATOMICCHANGELISTENER_HXX
|
||||
#define SIMGEAR_ATOMICCHANGELISTENER_HXX 1
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/structure/Singleton.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
#include "ExtendedPropertyAdapter.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
// Performs an action when one of several nodes changes
|
||||
class MultiChangeListener : public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
MultiChangeListener();
|
||||
template<typename Pitr>
|
||||
void listenToProperties(Pitr propsBegin, Pitr propsEnd)
|
||||
{
|
||||
for (Pitr itr = propsBegin, end = propsEnd; itr != end; ++itr)
|
||||
(*itr)->addChangeListener(this);
|
||||
}
|
||||
private:
|
||||
void valueChanged(SGPropertyNode* node);
|
||||
virtual void valueChangedImplementation();
|
||||
|
||||
};
|
||||
|
||||
class AtomicChangeListener : public MultiChangeListener,
|
||||
public virtual SGReferenced
|
||||
{
|
||||
public:
|
||||
AtomicChangeListener(std::vector<SGPropertyNode*>& nodes);
|
||||
/**
|
||||
* Lookup / create child nodes from their relative names.
|
||||
*/
|
||||
template<typename Itr>
|
||||
AtomicChangeListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||
Itr childNamesEnd)
|
||||
: _dirty(false), _valid(true)
|
||||
{
|
||||
using namespace std;
|
||||
for (Itr itr = childNamesBegin, end = childNamesEnd;
|
||||
itr != end;
|
||||
++itr)
|
||||
_watched.push_back(makeNode(parent, *itr));
|
||||
listenToProperties(_watched.begin(), _watched.end());
|
||||
}
|
||||
bool isDirty() { return _dirty; }
|
||||
bool isValid() { return _valid; }
|
||||
void unregister_property(SGPropertyNode* node);
|
||||
static void fireChangeListeners();
|
||||
private:
|
||||
virtual void valueChangedImplementation();
|
||||
virtual void valuesChanged();
|
||||
bool _dirty;
|
||||
bool _valid;
|
||||
struct ListenerListSingleton : public Singleton<ListenerListSingleton>
|
||||
{
|
||||
std::vector<SGSharedPtr<AtomicChangeListener> > listeners;
|
||||
};
|
||||
protected:
|
||||
std::vector<SGPropertyNode*> _watched;
|
||||
};
|
||||
|
||||
template<typename T, typename Func>
|
||||
class ExtendedPropListener : public AtomicChangeListener
|
||||
{
|
||||
public:
|
||||
ExtendedPropListener(std::vector<SGPropertyNode*>& nodes, const Func& func,
|
||||
bool initial = false)
|
||||
: AtomicChangeListener(nodes), _func(func)
|
||||
{
|
||||
if (initial)
|
||||
valuesChanged();
|
||||
|
||||
}
|
||||
template<typename Itr>
|
||||
ExtendedPropListener(SGPropertyNode* parent, Itr childNamesBegin,
|
||||
Itr childNamesEnd, const Func& func,
|
||||
bool initial = false)
|
||||
: AtomicChangeListener(parent, childNamesBegin, childNamesEnd),
|
||||
_func(func)
|
||||
{
|
||||
if (initial)
|
||||
valuesChanged();
|
||||
}
|
||||
virtual void valuesChanged()
|
||||
{
|
||||
ExtendedPropertyAdapter<T, std::vector<SGPropertyNode*> > adaptor(_watched);
|
||||
T val = adaptor();
|
||||
_func(val);
|
||||
}
|
||||
private:
|
||||
Func _func;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX
|
||||
#define SIMGEAR_EXTENDEDPROPERTYADAPTER_HXX 1
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
namespace props
|
||||
{
|
||||
// This should be in simgear/math/SGVec.hxx and friends
|
||||
|
||||
template<typename T> struct NumComponents;
|
||||
|
||||
template<> struct NumComponents<SGVec3d>
|
||||
{
|
||||
enum { num_components = 3 };
|
||||
};
|
||||
|
||||
template<> struct NumComponents<SGVec4d>
|
||||
{
|
||||
enum { num_components = 4 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename NodeContainer>
|
||||
class ExtendedPropertyAdapter
|
||||
{
|
||||
public:
|
||||
enum { num_components = props::NumComponents<T>::num_components };
|
||||
ExtendedPropertyAdapter(const NodeContainer& elements)
|
||||
: _elements(elements)
|
||||
{
|
||||
}
|
||||
T operator()() const
|
||||
{
|
||||
T result;
|
||||
if (_elements.size() < num_components)
|
||||
throw sg_exception();
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
result[i] = _elements[i]->getValue<double>();
|
||||
return result;
|
||||
}
|
||||
void set(const T& val)
|
||||
{
|
||||
if (_elements.size() < num_components)
|
||||
throw sg_exception();
|
||||
for (int i = 0; i < num_components; ++i)
|
||||
_elements[i]->setValue(val[i]);
|
||||
}
|
||||
private:
|
||||
const NodeContainer& _elements;
|
||||
};
|
||||
|
||||
template<typename InIterator, typename OutIterator>
|
||||
inline void makeChildList(SGPropertyNode* prop, InIterator inBegin,
|
||||
InIterator inEnd, OutIterator outBegin)
|
||||
{
|
||||
std::transform(inBegin, inEnd, outBegin,
|
||||
boost::bind(static_cast<SGPropertyNode* (SGPropertyNode::*)(const char*, int, bool)>(&SGPropertyNode::getChild), prop, _1, 0, true));
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -5,12 +5,15 @@ lib_LIBRARIES = libsgprops.a
|
||||
include_HEADERS = \
|
||||
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;
|
||||
}
|
||||
|
||||
+24
-7
@@ -52,7 +52,7 @@ private:
|
||||
route_list route;
|
||||
int current_wp;
|
||||
|
||||
void update_distance(int index);
|
||||
void update_distance_and_track(int index);
|
||||
|
||||
public:
|
||||
|
||||
@@ -102,6 +102,22 @@ public:
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
inline SGWayPoint get_previous() const {
|
||||
if ( (current_wp > 0) && (current_wp < (int)route.size()) ) {
|
||||
return route[current_wp - 1];
|
||||
} else {
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
inline SGWayPoint get_next() const {
|
||||
if ( (current_wp + 1) < (int)route.size() ) {
|
||||
return route[current_wp+1];
|
||||
} else {
|
||||
return SGWayPoint( 0.0, 0.0, 0.0, SGWayPoint::WGS84, "invalid" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current waypoint
|
||||
@@ -113,6 +129,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline int current_index() const {
|
||||
return current_wp;
|
||||
}
|
||||
|
||||
/** Increment the current waypoint pointer. */
|
||||
inline void increment_current() {
|
||||
if ( current_wp < (int)route.size() - 1 ) {
|
||||
@@ -138,14 +158,11 @@ public:
|
||||
|
||||
/** Delete waypoint waypoint with index n (last one if n < 0) */
|
||||
void delete_waypoint( int n = 0 );
|
||||
|
||||
|
||||
/**
|
||||
* Calculate perpendicular distance from the current route segment
|
||||
* This routine assumes all points are laying on a flat plane and
|
||||
* ignores the altitude (or Z) dimension. For most accurate
|
||||
* results, use with CARTESIAN way points.
|
||||
* Helper, sum the distance members of each waypoint
|
||||
*/
|
||||
double distance_off_route( double x, double y ) const;
|
||||
double total_distance() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ void dump_route(const SGRoute& route, const char* message)
|
||||
int main()
|
||||
{
|
||||
SGRoute route;
|
||||
|
||||
/*
|
||||
route.add_waypoint( SGWayPoint(0, 0, 0, SGWayPoint::CARTESIAN, "Start") );
|
||||
route.add_waypoint( SGWayPoint(1, 0, 0, SGWayPoint::CARTESIAN, "1") );
|
||||
route.add_waypoint( SGWayPoint(2, 0, 0, SGWayPoint::CARTESIAN, "2") );
|
||||
@@ -48,6 +48,6 @@ int main()
|
||||
|
||||
route.add_waypoint(wp2, 3);
|
||||
dump_route(route, "added back WP2 after WP3");
|
||||
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
+24
-32
@@ -29,23 +29,38 @@
|
||||
|
||||
#include "waypoint.hxx"
|
||||
|
||||
using std::string;
|
||||
|
||||
// Constructor
|
||||
SGWayPoint::SGWayPoint( const double lon, const double lat, const double alt,
|
||||
const modetype m, const string& s, const string& n ) {
|
||||
target_lon = lon;
|
||||
target_lat = lat;
|
||||
target_alt = alt;
|
||||
mode = m;
|
||||
id = s;
|
||||
name = n;
|
||||
const modetype, const string& s, const string& n ) :
|
||||
pos(SGGeod::fromDegM(lon, lat, alt)),
|
||||
id(s),
|
||||
name(n),
|
||||
_distance(0.0),
|
||||
_track(0.0),
|
||||
_speed(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
SGWayPoint::SGWayPoint(const SGGeod& geod, const string& s, const string& n ) :
|
||||
pos(geod),
|
||||
id(s),
|
||||
name(n),
|
||||
_distance(0.0),
|
||||
_track(0.0),
|
||||
_speed(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
SGWayPoint::~SGWayPoint() {
|
||||
}
|
||||
|
||||
void SGWayPoint::CourseAndDistance(const SGGeod& cur, double& course, double& dist ) const {
|
||||
double reverse;
|
||||
SGGeodesy::inverse(cur, pos, course, reverse, dist);
|
||||
}
|
||||
|
||||
// Calculate course and distances. For WGS84 and SPHERICAL
|
||||
// coordinates lat, lon, and course are in degrees, alt and distance
|
||||
@@ -55,34 +70,11 @@ void SGWayPoint::CourseAndDistance( const double cur_lon,
|
||||
const double cur_lat,
|
||||
const double cur_alt,
|
||||
double *course, double *dist ) const {
|
||||
if ( mode == WGS84 ) {
|
||||
double reverse;
|
||||
geo_inverse_wgs_84( cur_alt, cur_lat, cur_lon, target_lat, target_lon,
|
||||
course, &reverse, dist );
|
||||
} else if ( mode == SPHERICAL ) {
|
||||
Point3D current( cur_lon * SGD_DEGREES_TO_RADIANS, cur_lat * SGD_DEGREES_TO_RADIANS, 0.0 );
|
||||
Point3D target( target_lon * SGD_DEGREES_TO_RADIANS, target_lat * SGD_DEGREES_TO_RADIANS, 0.0 );
|
||||
calc_gc_course_dist( current, target, course, dist );
|
||||
*course = 360.0 - *course * SGD_RADIANS_TO_DEGREES;
|
||||
} else if ( mode == CARTESIAN ) {
|
||||
double dx = target_lon - cur_lon;
|
||||
double dy = target_lat - cur_lat;
|
||||
*course = -atan2( dy, dx ) * SGD_RADIANS_TO_DEGREES - 90;
|
||||
while ( *course < 0 ) {
|
||||
*course += 360.0;
|
||||
}
|
||||
while ( *course > 360.0 ) {
|
||||
*course -= 360.0;
|
||||
}
|
||||
*dist = sqrt( dx * dx + dy * dy );
|
||||
}
|
||||
CourseAndDistance(SGGeod::fromDegM(cur_lon, cur_lat, cur_alt), *course, *dist);
|
||||
}
|
||||
|
||||
// Calculate course and distances between two waypoints
|
||||
void SGWayPoint::CourseAndDistance( const SGWayPoint &wp,
|
||||
double *course, double *dist ) const {
|
||||
CourseAndDistance( wp.get_target_lon(),
|
||||
wp.get_target_lat(),
|
||||
wp.get_target_alt(),
|
||||
course, dist );
|
||||
CourseAndDistance( wp.get_target(), *course, *dist );
|
||||
}
|
||||
|
||||
+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()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user