Compare commits

...

323 Commits

Author SHA1 Message Date
mfranz
0bcdf2e4dc easyxml.cxx: add missing endXML visitor call
testEasyXML.cxx: beef it up
2007-06-29 10:46:52 +00:00
mfranz
cd5a720211 Vivian MEAZZA: add support for aircraft radar signatures 2007-06-24 08:09:07 +00:00
mfranz
5cb04946b0 don't only complain that the volume is larger than 1.0, but say how much
it actually is
2007-06-23 16:48:01 +00:00
mfranz
c8953c6275 Maik JUSTUS: fix/implement directional sound 2007-06-21 21:46:21 +00:00
mfranz
e8dc9c9454 d'oh ... beautify the TRACE message that we actually see! :-} 2007-06-19 18:22:32 +00:00
mfranz
a0c325681f beautify TRACE message 2007-06-19 18:11:06 +00:00
mfranz
8d3bf19422 sooner than planned: fix "scale" animation offsets (1 -> 0) 2007-06-17 21:01:40 +00:00
fredb
4477867ef4 Update MSVC 7.1 projects 2007-06-16 16:14:23 +00:00
fredb
e696c884dc MSVC 7 compilation 2007-06-16 16:13:29 +00:00
mfranz
80bcaa49e6 Nick WARNE: add file name to screenshot info line 2007-06-14 20:20:18 +00:00
mfranz
0096c1bb02 advance tracing messages from SG_INFO to SG_ALERT. If a developer has
demanded tracing, then he shouldn't get these important messages buried
in thousands of lines of meaningless bulk.
2007-06-11 16:09:50 +00:00
mfranz
38b37a068d - allow for (rather unusual) ////// cloud groups
- fix potential use of uninitialized memory: dew
2007-06-09 18:36:56 +00:00
frohlich
0281f31df2 Modified Files:
simgear/scene/material/mat.cxx simgear/scene/material/mat.hxx
	simgear/scene/util/SGSceneFeatures.cxx
	simgear/scene/util/SGSceneFeatures.hxx:
	Olaf Flebbe: Make use of SGSceneFeatues for anisotropic filtering,
	clean up.
2007-06-08 06:50:16 +00:00
frohlich
40b182c550 Removed Files:
simgear/scene/tgdb/leaf.cxx: Now obsolete but not yet removed.
2007-06-08 06:40:56 +00:00
frohlich
d1dedc7511 Modified Files:
scene/tgdb/SGOceanTile.cxx: add missing transform for the ocean
	tile.
2007-06-03 18:28:14 +00:00
frohlich
04cd9b3eb6 Modified Files:
simgear/scene/model/model.cxx
	simgear/scene/util/SGSceneFeatures.cxx
	simgear/scene/util/SGSceneFeatures.hxx:
	Make sure textures are shared. Do not rely on a graphics
	context to be available on model loading.
2007-06-03 18:21:04 +00:00
andy
de6003367d Sync with Nasal upstream. Mostly fixes to naContinue(), which
FlightGear doesn't use.  Also includes a performance fix for the
call() builtin that should help Melchior, who was measuring lower
performance for the props.Node() interface than the getprop/setprop
API.
2007-05-30 22:49:41 +00:00
frohlich
a5f42eeddf Modified Files:
projects/VC8/SimGear.vcproj: Olaf FLebbe win32 build system.
2007-05-30 13:16:53 +00:00
frohlich
a8ba041b67 Modified Files:
simgear/scene/model/SGMaterialAnimation.cxx:
	Olaf Flebbe: Use brakets around bitwise operations.
	Greetings from LinuxTag, Berlin ... :)
2007-05-30 13:07:05 +00:00
curt
e700fc6f34 I guess we aren't using explicit destructors here. 2007-05-30 12:34:24 +00:00
curt
af29d3d257 Make an explicit destructor so the compiler doesn't get confused about
non matching exception types with the implicitely defined destructor.
2007-05-29 19:38:17 +00:00
frohlich
487701a143 Modified Files:
simgear/scene/model/Makefile.am
	simgear/scene/model/animation.cxx
	simgear/scene/model/animation.hxx
Added Files:
	simgear/scene/model/SGRotateTransform.cxx
	simgear/scene/model/SGRotateTransform.hxx
	simgear/scene/model/SGScaleTransform.cxx
	simgear/scene/model/SGScaleTransform.hxx
	simgear/scene/model/SGTranslateTransform.cxx
	simgear/scene/model/SGTranslateTransform.hxx:
	Factor out some useful classes.
2007-05-28 07:13:07 +00:00
frohlich
f32e037c58 Modified Files:
simgear/scene/material/mat.cxx simgear/scene/material/mat.hxx:
	Olaf Flebbe: Improoved texture filtering.
2007-05-28 05:13:03 +00:00
frohlich
8bd903dd96 Modified Files:
SGAtomic.hxx: Also use atomic compiler intrinsics on SGI
2007-05-28 05:06:14 +00:00
frohlich
560c100484 Modified Files:
simgear/bucket/newbucket.cxx simgear/bucket/newbucket.hxx
	simgear/io/decode_binobj.cxx simgear/io/sg_binobj.cxx
	simgear/io/sg_binobj.hxx simgear/math/SGVec2.hxx
	simgear/math/SGVec3.hxx simgear/math/SGVec4.hxx
	simgear/scene/material/mat.hxx
	simgear/scene/material/matlib.cxx
	simgear/scene/material/matlib.hxx
	simgear/scene/model/Makefile.am simgear/scene/tgdb/Makefile.am
	simgear/scene/tgdb/obj.cxx simgear/scene/tgdb/obj.hxx
	simgear/scene/tgdb/pt_lights.cxx
	simgear/scene/tgdb/pt_lights.hxx
	simgear/scene/util/Makefile.am
	simgear/scene/util/SGNodeMasks.hxx
	simgear/scene/util/SGTextureStateAttributeVisitor.cxx
Added Files:
	simgear/scene/model/SGOffsetTransform.cxx
	simgear/scene/model/SGOffsetTransform.hxx
	simgear/scene/tgdb/SGDirectionalLightBin.hxx
	simgear/scene/tgdb/SGLightBin.hxx
	simgear/scene/tgdb/SGOceanTile.cxx
	simgear/scene/tgdb/SGOceanTile.hxx
	simgear/scene/tgdb/SGTexturedTriangleBin.hxx
	simgear/scene/tgdb/SGTriangleBin.hxx
	simgear/scene/tgdb/SGVasiDrawable.cxx
	simgear/scene/tgdb/SGVasiDrawable.hxx
	simgear/scene/tgdb/SGVertexArrayBin.hxx
	simgear/scene/util/SGEnlargeBoundingBox.cxx
	simgear/scene/util/SGEnlargeBoundingBox.hxx
	simgear/scene/util/SGSceneFeatures.cxx
	simgear/scene/util/SGSceneFeatures.hxx
Removed Files:
	simgear/scene/tgdb/leaf.hxx simgear/scene/tgdb/vasi.hxx:
	Reorganize tile loaders.
	Build bigger leafs for the tiles.
	Move runway light colors into materials.xml.
	Split out classes that might be useful at other places.
	Avoid static storage on binobject loading.
2007-05-28 05:00:28 +00:00
andy
52444d177b GCC on ppc linux uses a different architecture symbol than the same compiler on OS X 2007-05-25 15:49:10 +00:00
frohlich
b4f7ff29ef Modified Files:
SGVec3.hxx: Fix a problem in perpendicular triangle computation.
	Solves problem with invalid triangles in ground picking ...
2007-05-18 07:29:37 +00:00
frohlich
f7c6a5bfa2 Modified Files:
SGVec2.hxx SGVec3.hxx SGVec4.hxx point3d.hxx: Provide ordering
	relations for use with std::less in tree bases std:: containers.
2007-05-18 04:46:11 +00:00
curt
6fe14f7a6b Fix a compiler warning. 2007-05-16 16:08:17 +00:00
curt
786e5addd8 Fix various compiler warnings. 2007-05-16 16:07:03 +00:00
mfranz
2e9a15f523 Tim Moore 2007-05-15 22:28:08 +00:00
mfranz
bb0d2ddc53 add Mathias and Maik (to make it look less selfish that I add myself :-)
I'm sure I forgot a lot of people, but it's a start.
2007-05-15 22:02:06 +00:00
mfranz
702fb014a5 s/resistence/resistance/ 2007-05-13 11:53:06 +00:00
frohlich
834eab9457 Modified Files:
simgear/bucket/newbucket.hxx simgear/scene/material/mat.cxx
	simgear/scene/material/matlib.cxx
	simgear/scene/material/matlib.hxx
	simgear/scene/model/location.cxx
	simgear/scene/tgdb/apt_signs.cxx simgear/scene/tgdb/leaf.cxx
	simgear/scene/tgdb/leaf.hxx simgear/scene/tgdb/obj.cxx
	simgear/scene/tgdb/obj.hxx
	simgear/scene/util/SGUpdateVisitor.hxx: Reorganize scenegraph to
	simplify top level structure.
2007-05-08 06:11:15 +00:00
mfranz
a85da04601 Add method to return the number of attached listeners. Listeners have become
a much more important feature than they were two years or something ago, and
it's helpful for debugging and exploration to get this important node property
shown in property tree dumps or in the property browser (verbose mode).
2007-05-07 14:03:44 +00:00
mfranz
414f1c27e4 - fix bug where a property tree saved with writeProperties() and read back
in with readProperties() would not look the same, because element indices
  of '0' were even dropped when a node has a "secret" value *and* children

- introduce "omit-node" modifier attribute for the "include" attribute.
  This inserts the given file in place of the including node, while the
  node is dropped. This is desirable for multiple includes (which can't
  be done by multiply using the "include" attribute, as this isn't valid
  XML spec syntax)
2007-05-06 17:33:15 +00:00
mfranz
c76e2eb900 better warning text for <global> in material animations 2007-05-05 11:16:35 +00:00
frohlich
c523e15302 Modified Files:
SGMaterialAnimation.cxx SGMaterialAnimation.hxx:
	Tim Moore: overhaul the material animation.
2007-05-05 09:15:18 +00:00
frohlich
2dc8de295d Modified Files:
simgear/scene/model/animation.hxx
	simgear/scene/model/shadanim.cxx: Tim Moore: the crom shader.
2007-05-03 19:46:13 +00:00
andy
d645fd6327 Empty vectors work much better as the result of sorting an empty array
than nil does...
2007-05-02 22:29:35 +00:00
andy
219a7f3a07 Fix crash when sorting newly-allocated empty vectors 2007-05-02 22:24:45 +00:00
mfranz
d95e3e0055 don't rely on a compressed scanline being properly closed
(GIMP apparently generates corrupted files)
2007-04-28 23:13:13 +00:00
mfranz
2cc31ff425 SGTexture::read_rgb(a)_texture:
- support greyscale and greyscale/alpha format
- cleanup & make it faster
2007-04-28 12:30:38 +00:00
frohlich
8258fd7d9f Modified Files:
projects/VC8/SimGear.vcproj: Olaf Flebbe: Updates to the win32
	build system.
2007-04-21 12:24:43 +00:00
frohlich
784cca2233 Modified Files:
simgear/scene/material/mat.cxx simgear/scene/material/mat.hxx:
	Olaf Flebbe: make anisotroüpic filtering configurable.
2007-04-21 12:13:16 +00:00
andy
436539a700 Melchior found a bug with negative values in default function arguments 2007-04-06 20:35:38 +00:00
andy
dcb3da9f28 sync with Nasal CVS (added a sort() builtin) 2007-04-06 14:52:06 +00:00
mfranz
a354c841f1 Csaba HALASZ:
- fix bug that messed up leg distances after inserting and deleting waypoints
  not at the end of the route
- move add_waypoint() and delete_waypoint from hxx to cxx
- beef up routetest
2007-04-06 09:54:35 +00:00
fredb
3824f064cd Update MSVC 7.1 projects 2007-04-03 11:35:19 +00:00
fredb
cba6db752b Avoid potential memory leak problems when exceptions are thrown by using reference objects 2007-04-03 11:25:07 +00:00
andy
a458e26581 Fix typo in _M_IX86 2007-04-02 21:32:41 +00:00
andy
9d68727a84 Rewrite substr() to properly clamp its argument ranges and handle negative start arguments as offset-from-end values 2007-04-02 18:28:38 +00:00
andy
38b9a874e0 Add missing free functions for win32 2007-04-02 17:34:47 +00:00
andy
7a680fb9f2 Use __FUNCTION__, which works on gcc and MSVC 7/8, instead of
__func__, which while standardized works only with gcc.  I'll wait for
bug reports from VC6 before bothering with fallback code...
2007-04-02 16:14:54 +00:00
andy
a5f9262adb Melchior points out that NaN/Inf behavior is not platform-independent.
So toss a runtime error ("floating point error") when any of the math
library functions produce a non-finite value.  Note that these are not
the only locations that can do that (simply dividing by zero will
produce an Inf), but it's still proper behavior.
2007-03-30 16:42:22 +00:00
andy
b05e32fa8c Sync with Nasal CVS (soon to become Nasal 1.1). Notable new features:
Nasal now supports calls to "subcontexts" and errors can be thrown
across them, leading to complete stack traces when call() is used,
instead of the truncated ones we now see.

Vectors can now be concatenated using the ~ operator that used to work
only for strings.

Better runtime error messages in general due to a fancier
naRuntimeError() implementation

A big data size shrink on 64 bit systems; the size of a naRef dropped
by a factor of two.

"Braceless code blocks" have been added to the parser, so you can
write expressions like "if(a) b();" just like in C.  Note that there's
still a parser bug in there that fails when you nest a braced block
within a braceless one.

Character constants that appear in Nasal source code can now be
literal multibyte UTF8 characters (this was always supported for
string literals, but character constants were forced to be a single
byte).

New modules: "bits", "thread", "utf8" and (gulp...) "io".  The bits
library might be useful to FlightGear, the utf8 one probably not as
Plib does not support wide character text rendering.  The thread
library will work fine for spawning threads to do Nasal stuff, but
obviously contact with the rest of FlightGear must be
hand-synchronized as FlightGear isn't threadsafe.  The io library is
no doubt the most useful, as it exposes all the basic stdio.h
facilities; it's also frighteningly dangerous when combined with
networked code...
2007-03-29 18:50:12 +00:00
mfranz
53d8cff835 Csaba HALASZ: when a path_cache ceases to exist, unregister from all nodes
that had been told that this node is linking to them

mf: remove old erase-by-key methods; they are now unused and always were
    problematic, so they won't be used in the future either
2007-02-17 10:50:49 +00:00
mfranz
00fe97ff88 - don't leak node in both hash_table:🪣:erase()
- remove bad code from hash_table:🪣:erase(const char *) that was
  introduced with the last patch. (This function isn't used anywhere and
  is scheduled for removal. Leaving it in for now as a reference.)
- remove leaves first in remove_from_path_caches()

- cosmetics: indentation, one trailing space, variable name change, comment
  (Sorrry for mixing that with actual code, but I think it's easy to see.)
2007-02-16 15:32:21 +00:00
andy
607511fd64 Don't crash when destroying a SGBinding object if the property node it
was loaded from lacks a parent.  Patch from ndim on IRC
2007-02-14 23:14:00 +00:00
mfranz
8663c265d8 Maik JUSTUS:
"""
- make every node maintain list of properties that link to it
- add functions to erase node by address from hash bucket/entry in their
  path caches, so that all references can be removed
- if a node is removed, it (and all children, grandchildren, ...) calls
  all linked properties to remove them from their path-cache


This fixes problems with the aerotow over multiplayer and maybe some
other problems, where nodes are queried by name.
"""
2007-02-11 11:05:23 +00:00
andy
6c5d35d6ce "bias" argument to texture animations by Ron Jensen 2007-02-07 19:21:24 +00:00
mfranz
95532cb318 fix error message 2007-02-05 21:41:40 +00:00
frohlich
4d91bc5908 Modified Files:
ephemeris.cxx ephemeris.hxx stardata.cxx:
	one must not do changes just before checkin,
	one most not do changes just before checkin,
	[ last message repeated 100 times ]
2007-02-02 18:16:42 +00:00
frohlich
b13900402d Modified Files:
ephemeris.cxx ephemeris.hxx stardata.cxx stardata.hxx: Throw out sg.h
2007-02-02 18:09:27 +00:00
frohlich
1bb6c03bd0 Modified Files:
simgear/scene/util/SGNodeMasks.hxx
	simgear/scene/model/animation.cxx:
	More finegrained cull masks
2007-02-02 07:00:54 +00:00
frohlich
1445949e31 Modified Files:
projects/VC8/SimGear.vcproj: Olaf Flebbe: renenable static build
2007-01-31 21:40:59 +00:00
frohlich
360d3834ca Modified Files:
SGIntersect.hxx SGVec3.hxx SGVec4.hxx: Add convinience methods
2007-01-30 20:12:15 +00:00
fredb
aacdcad529 restore 'double checked locking' 2007-01-29 08:19:13 +00:00
frohlich
ad9341835f Modified Files:
model.cxx: Better texture sharing, fix problem with rotation order
2007-01-28 20:04:56 +00:00
frohlich
b028adb6af Modified Files:
simgear/structure/SGAtomic.cxx: Plug memory leak originating from
	wrong atomic fallback operations.
2007-01-28 20:03:43 +00:00
fredb
39f683b272 Ensure a reference on the cube map texture is always held 2007-01-26 20:30:02 +00:00
ehofman
a6c46c89eb *** empty log message *** 2007-01-23 10:07:36 +00:00
fredb
d534cf6f02 Better fix for the constant scale factor problem 2007-01-21 11:15:36 +00:00
fredb
dd4326f7c4 Support constant scaling factor 2007-01-21 10:33:34 +00:00
fredb
40aecd688e Don't segfault when dir is empty 2007-01-16 21:34:18 +00:00
frohlich
63730a6e2c Modified Files:
animation.cxx: Add a visible configuration option to the pick
	animation.
2007-01-15 19:01:20 +00:00
frohlich
4d4d26aef8 Modified Files:
projects/VC8/SimGear.vcproj: Olaf Flebbe, MSVC8 buildsystem changes.
2007-01-15 17:32:17 +00:00
mfranz
de6b32d8c6 writePropeties(): create dir if necessary 2007-01-12 21:24:50 +00:00
fredb
a0af7f0524 Update MSVC 7.1 project file and fix win32 compilation 2007-01-09 21:58:04 +00:00
frohlich
c043bd3422 Modified Files:
SGSceneUserData.hxx SGSceneUserData.cxx: Remove default argument
2007-01-07 12:25:32 +00:00
frohlich
18ae1d6940 Modified Files:
animation.cxx: Change the pick animation to better handle different
	mouse buttons.
2007-01-07 11:53:21 +00:00
frohlich
d6f64f9773 Modified Files:
SGSceneUserData.hxx SGPickCallback.hxx Makefile.am
Added Files:
	SGSceneUserData.cxx: Cleanup and replace the pick callback with
	such a list.
2007-01-07 11:52:19 +00:00
frohlich
db99a4cb90 Modified Files:
animation.cxx: Add a button argument to that animation.
	The default is to accept any mouse button.
2007-01-07 08:34:03 +00:00
fredb
108689661f Add a prototype simgear_config.h for MSVC 7.1 and a rule to build it. 2007-01-06 17:01:58 +00:00
fredb
d3e00dba8e Add a prototype simgear_config.h for MSVC 7.1 and a rule to build it.
At Olaf requests, add MSVC 8 specific symbols to remove pedantic warnings
2007-01-06 16:52:50 +00:00
fredb
fcd33e5035 Remove redundant directory ( projects as a whole is already there ) 2007-01-06 16:47:57 +00:00
frohlich
af9082cd9f Modified Files:
moon.cxx: The moo's state like it was with plib
2007-01-06 15:08:40 +00:00
fredb
6a0bb18fca Refresh MSVC6 project file 2007-01-06 14:45:21 +00:00
fredb
8aa8d87781 Fix a typo 2007-01-06 14:44:54 +00:00
fredb
4998af8d7a Add SGBinding.[ch]xx to the MSVC 7.1 project 2007-01-04 22:24:23 +00:00
fredb
c6aa95f3f3 std::find is defined in <algorithm> 2007-01-04 22:23:40 +00:00
frohlich
481be29366 Modified Files:
Makefile.am animation.cxx animation.hxx: Add animation to execute
	a command on scenery pick
2007-01-04 12:55:16 +00:00
frohlich
3617b6ad8c Modified Files:
Makefile.am SGNodeMasks.hxx
Added Files:
	SGPickCallback.hxx SGSceneUserData.hxx: Preparations for generic
	scenery picking.
2007-01-04 12:52:50 +00:00
frohlich
3fb8e19a38 Modified Files:
condition.hxx: Also derive from SGReferenced
2007-01-04 12:51:13 +00:00
frohlich
2ea2f1b4f2 Modified Files:
Makefile.am commands.cxx commands.hxx
Added Files:
	SGBinding.cxx SGBinding.hxx: Move FGBinding to SGBinding
2007-01-04 12:47:12 +00:00
frohlich
26cb8ec4f1 Modified Files:
SGIntersect.hxx: Make it compile with win32
2006-12-28 13:25:14 +00:00
frohlich
7fe56bea86 Modified Files:
obj.cxx: Some kind of polygon offset for GL_POINTS.
2006-12-27 10:33:37 +00:00
frohlich
11b16b8a86 Modified Files:
Makefile.am SGReferenced.hxx
Added Files:
	SGAtomic.cxx SGAtomic.hxx:
	Make the reference counts thread safe.
2006-12-27 10:07:19 +00:00
frohlich
de020ee695 Modified Files:
Makefile.am SGMathTest.cxx SGQuat.hxx SGVec3.hxx
Added Files:
	SGBox.hxx SGGeometry.hxx SGGeometryFwd.hxx SGGeometryTest.cxx
	SGIntersect.hxx SGLineSegment.hxx SGPlane.hxx SGRay.hxx
	SGSphere.hxx SGTriangle.hxx:
	Small updates to the vector code, new geometry and collision
	classes for use with a bv tree to speed up collission tests.
	Also included is a rought unit test for the collissions.
2006-12-27 09:23:39 +00:00
ehofman
3b83487611 Wether you like it or not, MispPro needs these libraries referenced 2006-12-23 12:15:05 +00:00
fredb
09bab4f162 memcpy needs #include <string.h> 2006-12-17 17:52:15 +00:00
fredb
49fcc799ca Port jpgfactory to OSG 2006-12-16 17:29:16 +00:00
fredb
10bc803775 Project files for MSVC 7.1 aka .NET 2003 2006-12-16 13:12:48 +00:00
frohlich
4f40770fc6 Modified Files:
simgear/math/SGVec3.hxx: fix spelling
2006-12-14 05:24:16 +00:00
frohlich
a4495c6ef1 Modified Files:
simgear/scene/sky/bbcache.cxx simgear/scene/sky/bbcache.hxx
	simgear/scene/sky/cloudfield.cxx
2006-12-08 12:22:10 +00:00
frohlich
67d837c4ec Modified Files:
SGVec3.hxx: Generate any perpandicular vector to a given one.
2006-12-08 12:17:30 +00:00
frohlich
138825af6d Modified Files:
point3d.hxx: Add explicit conversion functions to SGVec*
2006-12-08 12:16:56 +00:00
frohlich
c093841336 Modified Files:
simgear/scene/model/animation.cxx: Fix a problem of muliple
	texturre transform not finding the correct configuration.
2006-12-05 06:14:41 +00:00
frohlich
2df1da4226 Return void instead of bool. 2006-12-05 05:43:13 +00:00
frohlich
2792d60e2d Modified Files:
simgear/screen/extensions.hxx: Make it compile on macos
2006-12-03 17:44:27 +00:00
frohlich
656a3ace07 Modified Files:
simgear/scene/material/mat.cxx: Put solid scenery into the
	opaque render bin
2006-12-03 17:27:46 +00:00
frohlich
aec8e88c14 Modified Files:
simgear/scene/util/SGNodeMasks.hxx: Add pickable bit
2006-12-03 17:02:40 +00:00
frohlich
bdd5ca140d Modified Files:
simgear/scene/model/Makefile.am
	simgear/scene/model/animation.cxx
	simgear/scene/model/animation.hxx
	simgear/scene/model/model.cxx
	simgear/scene/model/persparam.cxx
	simgear/scene/model/persparam.hxx
	simgear/scene/model/shadanim.cxx
Added Files:
	simgear/scene/model/SGMaterialAnimation.cxx
	simgear/scene/model/SGMaterialAnimation.hxx
	Big animation overhaul. Improoves animation correctness.
2006-12-03 16:57:20 +00:00
frohlich
8b3b0def03 Modified Files:
SGUpdateVisitor.hxx: Include light information.
2006-12-03 16:46:23 +00:00
frohlich
6440ece177 Modified Files:
SGMisc.hxx: Add clip and periodic normalize functions.
2006-12-02 15:59:23 +00:00
frohlich
bd3518637c Modified Files:
SGVec2.hxx SGVec3.hxx SGVec4.hxx: Add inf norm function
2006-12-02 15:57:55 +00:00
frohlich
aef2a1c484 Modified Files:
interpolater.cxx interpolater.hxx: Enable reading tables directly
	from our dom like tree.
2006-12-02 15:56:55 +00:00
frohlich
a4b28e5737 Modified Files:
simgear/scene/sky/oursun.cxx: Fix the 'sun has wrong size' bug.
	Thanks to Mark Akermann.
2006-11-27 17:11:35 +00:00
frohlich
a3bc2eb836 Modified Files:
simgear/math/interpolater.cxx simgear/math/interpolater.hxx
	simgear/props/condition.cxx simgear/props/condition.hxx
	simgear/scene/model/animation.cxx
	simgear/scene/model/animation.hxx: Optimize interpolation table
	lookup by using a std::map.
2006-11-21 18:44:54 +00:00
frohlich
3059da5805 Modified Files:
SGVec2.hxx SGVec3.hxx SGVec4.hxx: Implement min/max for vectors
2006-11-21 18:39:57 +00:00
frohlich
18d5a492c8 Modified Files:
model.cxx: Tweak model optimizations
2006-11-20 18:19:02 +00:00
frohlich
160b0ea7d9 Modified Files:
placementtrans.cxx placementtrans.hxx: Make use of that view
        information in the update visitor
2006-11-20 18:17:56 +00:00
frohlich
4dd1267bea Modified Files:
SGUpdateVisitor.hxx: Store some view imformation in the
	update visitor.
2006-11-20 18:15:34 +00:00
fredb
b5c4328682 Mac fix from Ima Sudonim 2006-11-18 18:58:51 +00:00
frohlich
571fc69ef4 Modified Files:
VC8/SimGear.vcproj: Import buildsystem from Olaf Flebbe
2006-11-14 21:15:20 +00:00
frohlich
f51595cfc9 Modified Files:
animation.hxx animation.cxx: Improove material/texture/blend animation
2006-11-14 21:09:44 +00:00
frohlich
d54aea0036 Modified Files:
animation.cxx animation.hxx: Fix crash on A-10 load
2006-11-12 10:32:42 +00:00
frohlich
51bb2974bc Modified Files:
model.cxx: Leave it to osg when to do mipmapping.
2006-11-12 07:28:59 +00:00
frohlich
7a859061fd Modified Files:
model.cxx: Reset the database path past the whole model is loaded
2006-11-12 07:23:42 +00:00
frohlich
cefa9fcd75 Modified Files:
SGQuat.hxx: Make const method const
2006-11-12 07:22:44 +00:00
frohlich
d3bacd0b73 Modified Files:
simgear/scene/material/mat.cxx
	simgear/scene/material/matlib.cxx simgear/scene/sky/cloud.cxx
	simgear/scene/sky/dome.cxx simgear/scene/sky/moon.cxx
	simgear/scene/sky/oursun.cxx simgear/scene/sky/sphere.cxx
	simgear/scene/sky/stars.cxx simgear/scene/tgdb/apt_signs.cxx
	simgear/scene/tgdb/leaf.cxx simgear/scene/tgdb/leaf.hxx
	simgear/scene/tgdb/obj.cxx simgear/scene/tgdb/pt_lights.cxx
	simgear/scene/util/SGDebugDrawCallback.hxx
	simgear/screen/Makefile.am: Use color arrays for every geode.
	Just use osg::Material instead of osg::Material and the associated
	mode.
2006-11-10 05:30:37 +00:00
frohlich
b94a98fc90 Modified Files:
scene/model/model.cxx: Next step in direction liveries
2006-11-09 05:42:06 +00:00
fredb
e0b2687231 copysign is already in compiler.h 2006-11-07 21:31:17 +00:00
frohlich
cc6179a4dd Modified Files:
simgear/screen/extensions.cxx simgear/screen/extensions.hxx: Avoid
	the assumption that with glx-1.4 glXGetProcAddress is available -
	use dlsym to get that function.
2006-11-07 17:49:36 +00:00
fredb
e947bac4a3 This class is for plib only 2006-11-07 07:22:48 +00:00
frohlich
11ecbb6ca7 Modified Files:
mat.cxx: Fix dark scenery problem.
2006-11-07 06:40:35 +00:00
frohlich
322789cd4c Modified Files:
simgear/Makefile.am: Make 'make distclean' work
2006-11-07 06:02:47 +00:00
frohlich
f28464dba0 Modified Files:
projects/VC8/SimGear.vcproj: Olaf Flebbe: updated project files
2006-11-07 05:55:46 +00:00
frohlich
8f6456b1f8 Modified Files:
simgear/scene/util/SGUpdateVisitor.hxx: Only traverse active
	children.
2006-11-07 05:47:00 +00:00
frohlich
1f32786c82 Modified Files:
simgear/scene/util/SGDebugDrawCallback.hxx
	simgear/math/SGQuat.hxx: Olaf Flebbe: Make it compile on some more
	win32 variants.
2006-11-07 05:46:25 +00:00
fredb
829c729ee9 Don't try to load textures when no name is given 2006-11-06 21:59:02 +00:00
fredb
5d3aacb892 Attempt to fix the APIENTRY problem. It looks like a problem in OSG, or a conflict between OSG and plib/pui 2006-11-03 18:08:46 +00:00
fredb
741e9c5ed5 For some reason I don't know yet, the APIENTRY stuff in osg/GL is broken for some files. Include the real windows.h until we find why. 2006-11-03 10:04:58 +00:00
fredb
1408c1b623 add copysign definition for MSVC 2006-11-03 09:57:02 +00:00
fredb
c256f8d09e Win32 compilation fix 2006-11-02 17:40:54 +00:00
frohlich
55c018c525 Modified Files:
SGMath.hxx: Attempt to help IRIX builds
2006-11-02 13:37:23 +00:00
frohlich
3fa94b5143 Modified Files:
projects/VC8/SimGear.sln projects/VC8/SimGear.vcproj: Import Olafs
	project files
2006-11-02 06:15:14 +00:00
frohlich
5127e2f89c Modified Files:
Makefile.am SGMath.hxx SGMathFwd.hxx SGMatrix.hxx SGQuat.hxx
Added Files:
	SGVec2.hxx
	Improove the matrix functions. Improove the quaterion functions.
	Add the 2d vector.
2006-11-01 21:25:21 +00:00
mfranz
3175fa3aca + .deps/ 2006-11-01 21:24:24 +00:00
frohlich
5614174b39 Modified Files:
simgear/scene/model/Makefile.am
	simgear/scene/model/animation.cxx
	simgear/scene/model/animation.hxx
	simgear/scene/model/modellib.cxx
	simgear/scene/model/modellib.hxx
Removed Files:
	simgear/scene/model/personality.cxx
	simgear/scene/model/personality.hxx:
	Updates to the animation system.
	Personality can be implemented easier now
2006-10-31 06:26:50 +00:00
frohlich
39fc52fe0a Modified Files:
Makefile.am SGStateAttributeVisitor.hxx
 	SGTextureStateAttributeVisitor.hxx
Added Files:
	SGStateAttributeVisitor.cxx SGTextureStateAttributeVisitor.cxx:
	Move implementation into cxx files
2006-10-31 06:14:38 +00:00
frohlich
81188705b1 Modified Files:
simgear/math/SGQuat.hxx: Initialize with zero not with null pointer
2006-10-31 05:37:45 +00:00
frohlich
63c4873d8a Modified Files:
simgear/screen/extensions.cxx simgear/screen/extensions.hxx:
	use glXGetProcAddress if approriate
2006-10-31 05:36:50 +00:00
frohlich
1a85dcd890 Modified Files:
simgear/timing/timestamp.hxx: Remove reimplemented default
	implementations
2006-10-31 05:33:48 +00:00
frohlich
27470fc504 Modified Files:
configure.ac: Add a configure flag for osg
2006-10-30 19:56:09 +00:00
mfranz
65d18445d3 Makefile(.in) 2006-10-29 20:08:27 +00:00
frohlich
84dd54b33a Modified Files:
configure.ac simgear/environment/visual_enviro.cxx
	simgear/ephemeris/ephemeris.cxx
	simgear/ephemeris/ephemeris.hxx simgear/ephemeris/stardata.cxx
	simgear/ephemeris/stardata.hxx simgear/math/SGMatrix.hxx
	simgear/math/SGQuat.hxx simgear/math/SGVec3.hxx
	simgear/math/SGVec4.hxx simgear/scene/Makefile.am
 	simgear/scene/material/mat.cxx simgear/scene/material/mat.hxx
	simgear/scene/material/matlib.cxx
	simgear/scene/material/matlib.hxx
	simgear/scene/material/matmodel.cxx
	simgear/scene/material/matmodel.hxx
	simgear/scene/model/Makefile.am
	simgear/scene/model/animation.cxx
	simgear/scene/model/animation.hxx
	simgear/scene/model/custtrans.hxx
	simgear/scene/model/model.cxx simgear/scene/model/model.hxx
	simgear/scene/model/modellib.cxx
	simgear/scene/model/modellib.hxx
	simgear/scene/model/personality.cxx
	simgear/scene/model/personality.hxx
	simgear/scene/model/placement.cxx
	simgear/scene/model/placement.hxx
	simgear/scene/model/placementtrans.cxx
	simgear/scene/model/placementtrans.hxx
	simgear/scene/model/shadanim.cxx
	simgear/scene/model/shadowvolume.hxx
	simgear/scene/sky/cloud.cxx simgear/scene/sky/cloud.hxx
	simgear/scene/sky/cloudfield.cxx simgear/scene/sky/dome.cxx
	simgear/scene/sky/dome.hxx simgear/scene/sky/moon.cxx
	simgear/scene/sky/moon.hxx simgear/scene/sky/newcloud.cxx
	simgear/scene/sky/oursun.cxx simgear/scene/sky/oursun.hxx
	simgear/scene/sky/sky.cxx simgear/scene/sky/sky.hxx
	simgear/scene/sky/sphere.cxx simgear/scene/sky/sphere.hxx
	simgear/scene/sky/stars.cxx simgear/scene/sky/stars.hxx
	simgear/scene/tgdb/apt_signs.cxx
	simgear/scene/tgdb/apt_signs.hxx simgear/scene/tgdb/leaf.cxx
	simgear/scene/tgdb/leaf.hxx simgear/scene/tgdb/obj.cxx
	simgear/scene/tgdb/obj.hxx simgear/scene/tgdb/pt_lights.cxx
	simgear/scene/tgdb/pt_lights.hxx
	simgear/scene/tgdb/userdata.cxx
	simgear/scene/tgdb/userdata.hxx simgear/scene/tgdb/vasi.hxx
	simgear/screen/jpgfactory.cxx simgear/screen/tr.cxx
	simgear/structure/Makefile.am simgear/threads/SGThread.hxx
Added Files:
	simgear/scene/util/Makefile.am
	simgear/scene/util/SGDebugDrawCallback.hxx
	simgear/scene/util/SGNodeMasks.hxx
	simgear/scene/util/SGStateAttributeVisitor.hxx
	simgear/scene/util/SGTextureStateAttributeVisitor.hxx
	simgear/scene/util/SGUpdateVisitor.hxx
Removed Files:
	simgear/screen/ssgEntityArray.cxx
	simgear/screen/ssgEntityArray.hxx
	simgear/structure/ssgSharedPtr.hxx
	Big BLOB on the way to OSG.
2006-10-29 19:27:08 +00:00
curt
7c410d36e3 wim van hoydonck:
Updated to World Magnetic Model 2005.
2006-10-28 22:12:48 +00:00
mfranz
98a603a570 - don't need a guarded pointer here
- shorten variable, fix indentation
2006-10-24 20:28:08 +00:00
mfranz
5876052170 allow to switch on/off at runtime a whole imported <model> via <condition>:
<model>
      <path>some/model.xml</path>
      <condition>
          <property>model/switch</property>
      </condition>
  </model>

Of course, one could add "select" animations for all <object-name> in the
<model>, but this is tedious and can hardly be done e.g. for all
objects in all instruments in $FG_ROOT/Aircraft/Instruments-3d/ etc.

The feature will be used in the bo105, so that civilian variants can
have a HSI instrument, where military variants have a TACAN etc.
2006-10-24 19:44:38 +00:00
durk
f8303b4623 Compile time fixes needed to build SimGear on recent cygwin versions. 2006-10-22 19:42:17 +00:00
durk
20005a7a22 Make configuration script compatible with "home-built" openal libraries
on cygwin.
2006-10-22 19:41:16 +00:00
mfranz
4f0bfbab21 - // This will come back and remove
- // the current item each time.  Is
- // that OK?

No, it is not OK. This messes up the vector and confuses the iterator.
And it leads to crashes. Better read the vector in reverse order.
2006-10-22 13:08:09 +00:00
curt
811442832e Step #1 towards abandoning the original point lighting scheme in favor of
sprite based lighting.
2006-10-19 03:36:22 +00:00
frohlich
40811311d7 Modified Files:
SimGear.vcproj: Import changes from Olaf
2006-09-30 07:11:16 +00:00
durk
198de211f8 Memory leak fix. 2006-09-30 05:11:25 +00:00
fredb
9f5412fa9d Win32 only : Don't alloc a console when it is not needed 2006-09-27 20:16:32 +00:00
fredb
0dc9de81ae Add a simple program to benchmark SGTimeStamp::stamp() 2006-09-02 11:21:22 +00:00
fredb
5b8f42ce5e Make the SGTimeStamp behave under Windows just like for other environments 2006-08-31 18:26:45 +00:00
fredb
5314274ed6 Use getNodeValue as initially planned 2006-08-28 19:38:23 +00:00
ehofman
c831856711 MispPro requires an explicit declaration. 2006-08-28 18:53:36 +00:00
curt
1bade6d796 Frederic Bouvier:
Make line feed behavior consistent between linux/windows.
2006-08-26 14:02:17 +00:00
fredb
629a4a950e Better encapsulation for personality 2006-08-25 19:25:56 +00:00
mfranz
aebb1f6ec8 compile (gcc 4.1.0)
("In member function 'T SGPersonalityParameter<T>::shuffle()':
28: error: there are no arguments to 'sg_random' that depend on a template
parameter, so a declaration of 'sg_random' must be available")
2006-08-24 23:03:52 +00:00
fredb
6e42bc55e0 Reorganize personality parameters and add personality to translate, blend and scale animations 2006-08-24 22:46:40 +00:00
frohlich
1235fba7ee Remove duplicate linker line in the resulting Makefile 2006-08-08 05:05:09 +00:00
fredb
7a459db022 Win32 fix 2006-07-30 21:02:36 +00:00
frohlich
607987def5 Remove fastmath funktions like discussed on the list.
Add a new header with forward declarations of the SGMath stuff.
2006-07-30 07:48:06 +00:00
frohlich
397ec62180 Clean up scenery center handling. 2006-07-27 16:34:32 +00:00
durk
9315210fbe Mark's dynamic sun color changes. 2006-07-27 05:15:20 +00:00
curt
5127990a43 Additional functionality for animated point lights (i.e. approach light
rabbits, REIL, VASI/PAPI, etc.)

This allows the calling layer (i.e. FlightGear) better control over the use
of OpenGL point drawing extensions.
2006-07-21 15:45:01 +00:00
curt
40ad2b155a Updated dist content. 2006-07-12 15:08:00 +00:00
mfranz
a0412d026c remove the last redundant "delete" check in all of fgfs/sg (except JSBSim) 2006-07-05 09:31:36 +00:00
andy
7d2134c488 The previous update (and, embarassingly, the "nasal 1.0" release I
announced on Freshmeat.net) was broken.  This is the proper
break/continue fix.
2006-07-05 02:52:06 +00:00
andy
d894f52b97 Been hacking at Nasal recently:
Fix bug with break/continue inside of a foreach or forindex: Don't pop
the vector/index inside OP_EACH, do it at the end of the loop.

In the process, discovered and fixed a scary corruption issue with
continue; it never really worked right, although simple usage was
likely to get away without crashing.  Both the continue's OP_BREAK and
the cleanup code at the end of a loop would pop the "mark" stack,
leading to an underflow.  Introduced an OP_CONTINUE which adjusts
stack but doesn't change markTop

Re-inline the PUSH macro.  This thing is called all over the place
from the inner loop.  If the problem is intra-expression side effects,
then just use another expression in the macro.

Return an empty vector when requesting zero-length subvec, not nil

Have call() return the call stack in the error vector; see docs on
plausible.org/nasal or ask Andy about this feature.

Default closure()'s level argument to zero, not nil

Add an optional "file name" argument to compile()
2006-07-03 05:13:27 +00:00
mfranz
735f475c24 actually query the <condition> that is already set up in SGShaderAnimation 2006-07-01 20:06:05 +00:00
mfranz
353dd73e24 add knots <-> feet-per-second conversion constants 2006-06-25 11:55:56 +00:00
fredb
49fe06498a Compile again on Win32 platforms 2006-06-17 22:02:32 +00:00
frohlich
bc95ec8084 Make at least the header aliasing safe. 2006-06-17 16:04:28 +00:00
frohlich
f79906bf16 Make it compile with gcc-3.3.6 2006-06-17 16:04:05 +00:00
fredb
b3262fcb80 Compile again on Win32 platforms 2006-06-16 10:03:38 +00:00
mfranz
52b8f924aa add float_to_int() rounding function from Cockpit/hud_opts.hxx. The original
file said "(c) FlightGear Project" and "probably written by Norman Vine".
2006-06-16 09:29:54 +00:00
frohlich
52f57160aa Add dist and distSqr functions 2006-06-15 19:13:24 +00:00
frohlich
6d4f23919c Remove unused extern decls 2006-06-15 19:12:57 +00:00
frohlich
899623f71b Remove deprecated, now unused functions. 2006-06-15 08:52:21 +00:00
frohlich
c5d677ac7b Small cleanups to the SGGeo[dc] classes, provide more hooks to use them directly 2006-06-15 08:27:31 +00:00
frohlich
c75270a9fc Use function argument in va_start instead of local variable. 2006-06-15 06:14:46 +00:00
frohlich
1588a379eb Remove now unused function 2006-06-11 13:59:59 +00:00
frohlich
72d2075828 Modified Files:
simgear/scene/material/mat.cxx simgear/scene/material/mat.hxx
	simgear/scene/material/matlib.cxx
	simgear/scene/material/matlib.hxx simgear/scene/tgdb/leaf.cxx
	simgear/scene/tgdb/obj.cxx
	Attach userdata to groundtile scenegraph leafs that contains
	a SGMaterial reference to the material of that leaf.
	Add (physical) material properties to the material definitions.
	Plug a memory leak with GlyphSigns.
2006-06-11 13:30:59 +00:00
frohlich
e99c682637 Preliminary material lookup hooks - still unoptimized. 2006-06-08 05:54:23 +00:00
mfranz
c815f70831 whoops, sorry (Yes, it *was* tested, but then I made another "trivial"
change and ...)
2006-05-24 10:16:09 +00:00
mfranz
0da50eaa79 if we are going to die we better tell all our listeners 2006-05-24 09:37:44 +00:00
mfranz
b0af84a549 add optional position argument to SGRoute::add_waypoint(). Default is -1,
which appends the WP like it used to. Valid vector indices insert the WP
at this position.
2006-05-08 11:31:16 +00:00
fredb
b9631e8521 Mac fix 2006-05-04 05:58:59 +00:00
fredb
f664f7a201 Fix the initial texture path problem. Loaders are setting the one given to ssgLoad as the default one behind our back :-( 2006-04-29 08:09:51 +00:00
fredb
f72b3882c3 Redefine the default PLIB loader behavior : don't clear the texture cache after every model load 2006-04-28 18:05:46 +00:00
mfranz
ea47a2973c add method to delete any waypoint (last waypoint if n is out of range) 2006-04-28 15:43:13 +00:00
frohlich
04be9ca670 Pigeons remaining fix for the soundmanager crashes. 2006-04-25 18:47:37 +00:00
mfranz
6f0baf6ca9 thanks to Erik's texture map I can now drop empty.rgb altogether and just
specify the same texture in the "foo.lighted" and "foo.unlighted" material
entry. This also allows to drop the state cloning and thereby solves the
most urgent apt_signs.cxx TODO. :-)
2006-04-22 13:41:06 +00:00
ehofman
1f5ec6b8d5 Add a texture cache mechanism. Fortunately this oly seems affective for empty.rgb ... 2006-04-22 09:38:14 +00:00
mfranz
a2a91520aa don't allow new command name to overwrite material name 2006-04-20 17:46:40 +00:00
mfranz
fd7b5d3de7 - don't use hard-coded emission values for unlighted signs, but load both
states from material.xml (separate <material> entries for now)
- clone state less often: not once per sign element, but once per material
  switch (TODO: clone only once per material)
2006-04-20 16:06:00 +00:00
mfranz
30ea844c43 fix "unknown.rgb" path (the wrong path was the reason why we always only
got plib's lowres red-white chequer-board pattern along with an error
message, and not ours ... which is much prettier, but also bigger.
(Should we downscale it?)
2006-04-20 15:20:40 +00:00
mfranz
efac53b121 make headers include headers they depend on, don't rely on the c(xx)
file to do that. (This is a requirement for header precompiling.)
2006-04-17 11:29:01 +00:00
mfranz
73c0ef59c1 rename OBJECT_TAXI_SIGN to OBJECT_SIGN. This isn't about taxi signs any
more, but all sorts of signs. Now is the best time to get rid of a
misleading name.
2006-04-14 14:50:08 +00:00
mfranz
7e65ab2d3b add <condition> support to textranslate & texrotate animation 2006-04-12 20:27:38 +00:00
mfranz
fec769f632 set sign orientation such, that when the sign heading=0, one looks straight
on the sign face when looking North
2006-04-12 12:13:03 +00:00
mfranz
90e42642b6 lower signs 2006-04-11 23:04:24 +00:00
mfranz
9d9610a882 add minimalistic backside to signs as a temporary solution 2006-04-11 21:32:15 +00:00
mfranz
1fc81f4b66 re-add hard-coded vertical distance. The coordinates should be surface
points and not add this distance, which depends on the sign housing/hardware,
after all.
2006-04-11 17:34:17 +00:00
mfranz
4f0b1e847c - commands do now have to start with @
- add commands @size, @material, @light
- make "BlackSign" texture default
- make @B, @R, @L, @Y open close their frames automatically (this can be
  avoided by setting the @material manually)
- add number variants for those 4 sign commands: @Y2, @B5, etc (according
  to the spec; defaulting to the respective biggest panel size, i.e. @B = @B3)
(detailed description will be added to $FG_ROOT/Docs/)
2006-04-11 15:57:08 +00:00
mfranz
9567ac32f2 remove obsolete files (on request by Christian Mayer, who has introduced them):
- they are not used anywhere in sg/fgfs
- and are very clearly *not* GPL compatible!
2006-04-10 16:36:52 +00:00
andy
8dd9cfa2a6 Manabu Nishiyama (non-FlightGear Nasal user) discovered an
uninitialized data bug in naHash_cget().  When the hashcode field of
naStr was introduced, I forgot to set it in this function, which
creates a temporary naStr on the stack.
2006-04-10 16:21:17 +00:00
mfranz
dbda8ef893 drop xscale member again, and use xsize/ysize instead. (One interface
element less to confuse people.)
2006-04-10 15:32:55 +00:00
mfranz
cd143c15d5 rewrite of OBJECT_TAXI_SIGN code. The name is a bit misleading, as this
type can also create runway signs. (/me thinks about changing that ...)
2006-04-09 19:51:00 +00:00
mfranz
509a388ccc support for font textures. They are normal (but rather lenghty) <material>,
but contain <glyph> entries with <name>, <left> and <right>. The latter two
describe where in the texture a letter or symbol begins and where it ends.
(range 0-1). <xscale> defines a horizontal scaling factor.
2006-04-09 19:21:13 +00:00
curt
76c6482495 v0.3.10 changes. 2006-04-05 18:42:45 +00:00
mfranz
010a44f831 protect ssg pointers to avoid occasional crashes (of course it would be
nicer if the Occluder would always get removed before its model branch,
but that's not easily enforcable)
2006-03-30 14:13:22 +00:00
curt
e6b0d644d4 v0.3.10-pre3 updates. 2006-03-27 18:48:36 +00:00
curt
02dc68c899 Olaf Flebbe:
Unfortunatly the original SimGear Project I submitted contained local
changes which I didn't intend to submit. Please use this file instead...
2006-03-27 16:32:15 +00:00
mfranz
11ac97cd09 If the author of this message isn't alerted enough to *fix* this, then I'm
sure the users won't do that either. This is regularly triggerd and leads
to meaningless error reports.
2006-03-26 08:22:26 +00:00
mfranz
61f6565321 more guarded pointers (we are still getting spurious crashes on exit because
of that)
2006-03-24 23:24:20 +00:00
curt
55d951f211 Initial revision. 2006-03-24 19:06:05 +00:00
mfranz
143ce6fcd5 remove so that complete dir can be dropped 2006-03-23 22:05:22 +00:00
curt
e264c6ad2e Updates to remove unneeded and old version of zlib source. 2006-03-23 21:59:59 +00:00
curt
036b6785f1 Remove old depricated files. There is a much newer version of zlib
available and just about every unix-based platform already comes with this.
2006-03-23 21:52:03 +00:00
curt
caf5cc90ae v0.3.10-pre2 updates. 2006-03-23 16:37:35 +00:00
mfranz
b05e98b1b6 Vassilii KHACHATUROV: rain fix, cleanup, read formerly hard-coded values
from provided node

"* minor redundant gl call in DrawCone2 optimized away (twice per frame)
* corrected the glRotatef() order in drawRain even further (a less
obvious mistake than before, which is noticed by looking skywards and wiggling
the mouse in the view direction change mode)
* all the "magic numbers" used in the rain rendering code have been
provided a default (based on the old hardcoded value) in a form of a
define, and a meaningfully named static member in SGEnviro"
2006-03-23 15:39:00 +00:00
mfranz
31d0779377 Vassilii KHACHATUROV: fix typos, add/fix comments, change variable names 2006-03-22 16:02:55 +00:00
andy
6b056e915e Oops, implement the previously-mentioned fix without breaking support
for omitting a length argument to mean "the rest of the vector".
2006-03-21 23:12:30 +00:00
andy
9d6c0dc580 The original code (rather oddly) interprets a length of zero in
subvec() to mean "the whole vector".  Melchior showed a use case
(removal of the first element from a vector) where getting a
zero-length subvector is actually desired.  And since I can't come up
with a good reason for why the "feature" was there in the first place,
out it goes...
2006-03-21 22:22:47 +00:00
andy
6e973e07f4 Melchior discovered that cmp() was just wrong, failing to actually
inspect the string pointers.  It also failed to properly sort strings
where one is a prefix of the other.  It looks to me like I just never
finished this, and it ended up in CVS because it just happened to
compile...
2006-03-21 21:57:00 +00:00
curt
c8098b9eac Updates for v0.3.10-pre1. 2006-03-20 19:22:20 +00:00
mfranz
ed20ce388a - better error message when submodel loading failed
- use alignmainmodel node in callback (not used anywhere yet)
2006-03-17 19:01:52 +00:00
andy
33e01e431d The handle gets nulled out if the user has closed the file; don't pass that
null to fclose() in a garbage collection destructor too...
2006-03-16 18:01:56 +00:00
andy
7d631e4959 Fix broken checkin in iolib.c. Also add the 'bits' library, which has a buf()
function needed to make convenient use of io.read().
2006-03-15 19:42:37 +00:00
andy
29eb566448 Melchior found the first bug -- report EOF as nil in readln(). 2006-03-15 19:35:30 +00:00
andy
a770d2a972 Add the Nasal I/O library so Melchior can play with it. Not enabled currently (see NasalSys.cxx in the flightgear CVS) 2006-03-15 18:09:50 +00:00
mfranz
688cffb031 --warnings 2006-03-14 15:55:24 +00:00
mfranz
2cccc26541 --warnings 2006-03-14 15:49:29 +00:00
mfranz
f96f083bb5 close zone.tab file after having read all entries 2006-03-14 12:58:28 +00:00
mfranz
2e078aff7d prevent animations from losing nodes, because other processes removed them
(We are currently getting a lot of aborts in the condition code when
running MP. I don't expect this to fix it, but a bug is a bug.)

(reviewed by Fred, who also fixed *my* bugs :-)
2006-03-14 10:38:06 +00:00
mfranz
bd1f192dc4 Better use a node that is very clearly not used by other services
(e.g. animations). The data class doesn't mind.
2006-03-12 18:56:48 +00:00
mfranz
b62f241051 activate model load/unload callback again. It turned out *not* to be the
cause for the MP crashes -- the same crashes did still occur without it.
2006-03-12 10:09:34 +00:00
ehofman
95d1ac354e Mac OS X fixes from Ima Sudonim. 2006-03-11 22:20:19 +00:00
mfranz
54728f5d57 commenting out Nasal in scenery models for now. This could be responsible
for an MP/AI crash. Still investigating.
2006-03-10 22:58:24 +00:00
mfranz
d9356b0f86 warning-- 2006-03-09 16:17:35 +00:00
ehofman
6b68d9d90b Alexander Powell:
Add MAC OS X Render Texture support:

Most texture modes seem to work on my Powerbook, but I don't have a wide array
of machines to test it on otherwise.

If you have problems, please let me know and I'll see if I can help track down
the source of the bug.  I'd love to keep working on it if time permits (I use
RenderTexture in a few other projects), so I'll keep you informed if there are
any changes that I make for the better.
2006-03-09 09:54:43 +00:00
mfranz
359a8c4a81 model.[ch]xx:
add abstract class SGModelData. If a pointer to such a class is handed over
  to sgLoad3DModel, then its modelLoaded() method is called with path, property
  node and branch. And then it's added to the scene graph so that it's
  destroyed when the model branch is removed from the graph.

modellib.[ch]xx:
  only cache objects when asked to. This is the case for OBJECT_SHARED
  and random objects (like before), but no longer for OBJECT_STATIC.
  These are now removed from the graph when they are "out of sight". This
  prevents accumulation of static models, and makes destroying model data
  possible (e.g. removing Nasal modules)

matmodel.cxx:
  set cache flag for random objects (same behavior as before)
2006-03-09 09:03:57 +00:00
mfranz
dcb95d131b - new FSF addresses
- coplied license headers from h(xx) files to respective c(xx) files
- removed trailing spaces
- fixe $Id$
- fixed typos
2006-03-08 18:16:08 +00:00
david
f4e37ba7c0 Ignore generated binaries. 2006-03-04 13:27:11 +00:00
ehofman
1cbceec0e1 Mathias Frhlich:
zero out all parent pointers, else they might be dangling.
2006-03-04 12:46:29 +00:00
ehofman
5b3c5407a1 Mathias Frhlich:
I have some bugfixes which will avoid fg just crashing if the sound device
could not be opened.
2006-03-03 15:11:35 +00:00
fredb
27a120c7c3 Wrong config file name 2006-02-26 11:02:21 +00:00
andy
375f3e8bc1 Fix from Melchior: Set static values at every condition change, not only initially. 2006-02-22 20:50:35 +00:00
fredb
a75b4af374 Melchior FRANZ:
- don't unlock an already unlocked mutex (Someone wanted to be on
  the safe side with this, but the result is undefined and makes
  pthread_mutex_destroy fail. Reference: manpage for
  pthread_mutexattr_gettype/The Open Group[1]: "Attempting to
  unlock a mutex of this type which is not locked results in
  undefined behaviour.")

- re-enabled all subsystem destructors again (this has been disabled
  because fgfs hung on exit, due to the mutex destroy failure from
  above.)


Reference:
  http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_mutexattr_gettype.html
2006-02-21 12:59:31 +00:00
ehofman
b2a4cd488d Back out the previous patch. 2006-02-21 10:47:20 +00:00
ehofman
1d8d203e9e Declare specified functions, otherwise MIPSpro bails out. 2006-02-21 09:48:33 +00:00
ehofman
4e7fe460a5 Melchior FRANZ:
- new FSF address
- removed a few hundred trailing spaces
- fixed a few $Id$ lines
- copied two license headers from *.hxx files to their respective
  *.cxx counterparts
- added two test aps to .cvsignore
- don't unlock an already unlocked mutex (Someone wanted to be on
  the safe side with this, but the result is undefined and makes
  pthread_mutex_destroy fail. Reference: manpage for
  pthread_mutexattr_gettype/The Open Group[1]: "Attempting to
  unlock a mutex of this type which is not locked results in
  undefined behaviour.")
- re-enabled all subsystem destructors again (this has been disabled
  because fgfs hung on exit, due to the mutex destroy failure)
2006-02-21 09:40:12 +00:00
ehofman
9be14a63b1 Mathias Froehlich: Add license information. 2006-02-20 15:12:13 +00:00
ehofman
afd3c76088 Mathias Frhlich:
This patch makes use of the vectors now available in simgear with that past
patch. And using that it simplyfies the carrier code somehow.

- Small additional factory's to the quaternion code are done in the simgear
  part. Also more explicit unit names in the factory functions.
- The flightgear part makes use of them and simplyfies some computations
  especially in the carrier code.
- The data part fixes the coordinate frames I used for the park positions in
  the carrier to match the usual ones. I believed that I had done so, but it
  was definitly different. Also there are more parking positions avaliable now.
2006-02-19 17:22:17 +00:00
ehofman
6b697506c3 Melchior FRANZ:
- change SG back to FG (this was accidently changed in three wrong
  places when I prepared the file for SG)
- correct length for the proxy id detection
- set (guessed) deposit depth < 1mm correctly
- set deposit type string
- formatting
2006-02-19 17:13:37 +00:00
fredb
3eba296157 Missing defines 2006-02-18 16:19:54 +00:00
fredb
1b51de08f5 Add missing include files needed by the new math code under windows 2006-02-18 13:24:24 +00:00
fredb
3e37f3fa54 Fix Code generation option for debug build 2006-02-18 12:04:37 +00:00
fredb
a18679e95d Remove compiler warnings 2006-02-17 21:57:13 +00:00
curt
0154f81e33 Clean up some compiler warnings. 2006-02-17 15:13:42 +00:00
ehofman
366931952b Remove unused files. 2006-02-17 09:59:27 +00:00
ehofman
606fc352aa Melchior FRANZ:
This patch fixes the sound of 737, Concorde and others, if fgfs
was compiled with newer gcc versions (e.g. gcc 4.0.2). These compilers
implement the c++ standard more strictly, and thus don't guarantee
that c-style casted pointers to different data types really point
to the same address. This is only guaranteed for union members.
2006-02-17 09:23:40 +00:00
ehofman
75f817b39c Mathias Frhlich:
The patch adds a vector lib I have put together during the last time,
it is just handy and interfaces well with s(s)g*. Together with some small
modifications this will later also interface well with OpenSceneGraphs
vectors/matrices. Using this vector kernel is targeted to have a handy
matrix/vector lib available and to provide a scenegraph independent vector
type for use with a small scenegraph wrapper aimed for a smooth transition to
openscenegraph.

That vector code also includes an improoved geodetic conversion routine I
have found some time ago published in the 'journal of geodesy' which avoids
iterative computations for that purpose.

Also the geodetic position class is more typesafe and unitsafe than the
Point3D currently is.

That part is relatively old and in use in my local trees for several months
now.
2006-02-17 09:22:04 +00:00
ehofman
0bc49bf244 Olaf Flebbe:
This patch makesFlightGear at least compile on MSVC. I hope I have removed
reference of my other local changes. DSP and DSW files are included for
reference. They have been reconstructed with am2dsp.pl. I had to introduce a
change to am2dsp because of the need of filenames with embedded spaces. (Yuck)

The major direction is to remove clutter like the _USE_MATH_DEFINES and
have it on the compiler command line sice there is no central include
file. You will have to put it on the command line for your locale
Project files, if it not there, already. I added the
_CRT_SECURE_NO_DEPRECATE define for 2005, since it does no harm to other
VC version.

Third Party Libs like plib, OpenALSDK, freeglut, pthreads-win32, zlib
are unpacked as is side by side. Only change put the includes of OpenAL
into include/AL rather directly into include.
2006-02-17 08:58:56 +00:00
fredb
930a84b459 Outputing 6 digits is not enough for a double 2006-02-07 20:50:35 +00:00
ehofman
21c89e8163 Vassilii Khachaturov:
Fix the current buggy rain orientation behaviour for the views attached to the
aircraft (while still inheriting bugs with the views attached to anything else).
2006-02-02 09:56:48 +00:00
ehofman
b3770cd26c Expose the sun halo texture handle. 2006-01-31 15:14:02 +00:00
ehofman
0cd4d44bd3 Expose GL_COORD_REPLACE 2006-01-31 15:13:12 +00:00
ehofman
af15e73e64 create an absolute value before calling log or log10, this adds support for sound on negative numbers (thrust reverse for example). 2006-01-30 20:30:56 +00:00
ehofman
33f176b8f9 Melchior FRANZ:
add optional arg to SGPropertyNode::addChangeListener that triggers
the listener function call initially. This is useful for cases where
a freshly installed listener wants to treat the current property
value as changed from 'unknown' to the actual value right away.

Examples can be found in the Nasal incarnation setlistener(),
where we have for example this (in $FG_ROOT/Nasal/gui.nas):

  INIT = func {
      ...
      setlistener("/sim/rendering/fps-display", fpsDisplay);
      if (getprop("/sim/rendering/fps-display")) {
          fgcommand("dialog-show", props.Node.new({"dialog-name": "fps"}));
      }
  }


That is: we first attach a listener that cares for changes to the FPS
display switch, but then we have to manually open the dialog initially.
That's a duplication of code and could be as simple as this
(INIT part only):

  INIT = func {
      ...
      setlistener("/sim/rendering/fps-display", fpsDisplay, 1);
  }

That is: the optional third arg makes fpsDisplay be called initially,
and then again with every write action. My first solution was in the
Nasal code only, but Andy (rightfully) says that this should rather
be in sg.
2006-01-30 10:56:34 +00:00
ehofman
42f21972fd On a second thought, disable smooth shaded lines for all segments of the lightning. 2006-01-27 15:27:43 +00:00
ehofman
2d79e54c46 Disable smooth lines for certain lightning segments. 2006-01-27 15:18:45 +00:00
ehofman
224408b0e8 Add support for point sprites. 2006-01-26 09:15:42 +00:00
fredb
610e447d7c The sample is now managed by a SGSharedPtr and shouldn't be deleted explicitely 2006-01-24 21:49:56 +00:00
ehofman
c2c0e19305 Mathias Frhlich:
Incorporating the shared ptr code:
- All scenegraph references from SimGear
- SGMaterial which already had a reference counter uses now that common
  infrastructure.
- SGMatModel is now counted.
- SGSoundSample from SimGear
- And the corresponding change for the sound samples in flightgear which fixes
  a latent crash if FGBeacon would evern be deleted.
2006-01-24 14:44:35 +00:00
ehofman
e8c4b0d57c Mathias Frhlich:
Use the new automatic reference counter instead of doing
that ourselfes.
2006-01-12 13:47:04 +00:00
fredb
36e7684d9a MSVC vsnprintf ( in fact _vsnprinft ) returns -1 when the buffer is too short 2006-01-10 20:25:46 +00:00
fredb
795c079af0 Use the new SGPath::create_dir function
Ensure no triangles array could have more than 32767 vertices, a PLIB limit.
2006-01-07 13:21:36 +00:00
curt
94e1d3f0fc John Ellson:
This patch fixes this SimGear compile error on x86_64 Fedora Development with gcc-4.1:

placement.hxx:49: error: extra qualification ‘SGModelPlacement::’ on member ‘init’
2006-01-04 16:44:08 +00:00
ehofman
1df002de81 MinGW fixes. 2006-01-04 09:08:35 +00:00
ehofman
b7115659b3 Make the sgi code the default to prevent future problems. 2006-01-03 17:40:49 +00:00
ehofman
258ec6b89a Save some memory. 2006-01-03 17:34:00 +00:00
ehofman
d1ecdfc510 Fix the persisent IRIX bug. 2006-01-02 13:32:16 +00:00
ehofman
a807e66d4a prevent confusion by not using a standard name. 2006-01-02 10:04:10 +00:00
ehofman
8f9921d00c Mathias Frhlich:
Add the basic infrastructure for a reference counter class.
Adding it now (without using it) enables Mathias and others to
prepare some memory reduction code.
2005-12-29 12:00:29 +00:00
ehofman
99bc4e9a87 Vassilii Khachaturov:
clean up some build warnings caught with gcc-4.0.
2005-12-19 12:52:02 +00:00
ehofman
9289cfdde9 Frederic Bouvier:
Fix a problem where the directory being created is made relative when in fact
it's absolute. It also tightens things a bit on the Windows side.

Erik:

Make the section that splits up the directory in a lists of parent directories
a standalone function.
2005-12-19 10:22:27 +00:00
ehofman
bedbe3caad Frederic: this patch to sg_path.cxx will filter out false alarms when directory already exists. 2005-12-18 09:37:37 +00:00
ehofman
2e329426ab Frederic Bouvier:
The create_dir was totally broken. No function was used at the right place
except mkdir. This patch now create directories without segfaulting.


Erik:

This was my bad, I've been using a really slow computer for the last ten months
and recompiling SimGear with a change to the properties code takes ages, so
once in a while I apply something not entirely tested. This is one really bad
example which shouldn't have happened. Thanks to Frederic for fixing it.
2005-12-17 22:12:53 +00:00
ehofman
4c68d03457 Add the subdir to the path before trying to create it, instead of afterwards. 2005-12-17 15:41:48 +00:00
ehofman
0911fa4fa2 MSVC fixes. 2005-12-17 15:32:43 +00:00
ehofman
c5737c5f74 Try to detect the proper type for mode_t 2005-12-17 15:15:09 +00:00
ehofman
106198fa20 Stefan Seifert: Add the posibility to specify a userarchive attribute which could be used to save user prefferences at program exit. 2005-12-17 15:11:37 +00:00
ehofman
4eb74a3c93 Add a function to create aa new directory 2005-12-17 15:06:56 +00:00
ehofman
3f0bcc9568 Mathias Frhlich:
Detect whether we support pubuffers at runtime using the GLX extension string.


Erik:

Add support to compile TestRenderTexture if GLUT is installed.
2005-12-14 10:28:16 +00:00
ehofman
f0c35fde6d MacOs X fix. 2005-12-11 13:41:57 +00:00
ehofman
8357eeb762 Vassilii Khachaturov:
* in some cases more specific sg exception types were used in place
  of the more generic one, e.g., sg_io_exception instead of sg_exception
  when the context of the error was an IO error
* in some cases, the error message was made more specific
* minor style fix for exception rethrowing --- using throw; whenever
  a re-throw is made; sometimes optimizing away the exception symbol name
  in the catch handler at all
* more specific catch handlers added in some places -- e.g.,
  an sg_io_exception caught ahead of sg_exception
2005-12-11 13:35:05 +00:00
ehofman
61da54d6ca add swap_test to .cvsignore 2005-12-11 13:26:30 +00:00
ehofman
efea47833d Add a proper return statement for MSVC. 2005-12-11 12:51:51 +00:00
ehofman
24ea08b6d3 Vassilii: help those
using the Doxygen docs.
2005-12-06 18:45:14 +00:00
ehofman
2808b334ed Mathias: silence some valgrind warnings so that you can concentrate better on the real problems. 2005-12-06 18:29:28 +00:00
ehofman
96159cf739 How did this end up there?? 2005-11-27 09:48:51 +00:00
ehofman
577dfa4f54 Initialize glut before using it. 2005-11-27 09:46:58 +00:00
ehofman
66075d620e More WIN32 fixes. 2005-11-23 09:28:02 +00:00
ehofman
60f1d21914 Oops, WIN32 typo fix. 2005-11-22 18:42:16 +00:00
ehofman
b108621a59 * Use SimGear's logging facility isntead of printf's.
* Hopefuly fix a nasty (mostly ATI related) bug.
2005-11-22 18:03:26 +00:00
335 changed files with 24192 additions and 12305 deletions

View File

@@ -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 = 0.3.9
PROJECT_NUMBER = 0.3.10
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
@@ -303,16 +303,19 @@ INPUT = \
simgear/compiler.h \
simgear/constants.h \
simgear/debug \
simgear/environment \
simgear/ephemeris \
simgear/io \
simgear/magvar \
simgear/math \
simgear/misc \
simgear/nasal \
simgear/props \
simgear/route \
simgear/scene \
simgear/screen \
simgear/serial \
simgear/structure \
simgear/sg_inlines.h \
simgear/sg_traits.hxx \
simgear/sound \

View File

@@ -4,13 +4,15 @@ EXTRA_DIST = \
DoxygenMain.cxx \
README.MSVC \
README.zlib \
projects \
SimGear.dsp \
SimGear.dsw
SUBDIRS = src-libs simgear
SUBDIRS = simgear
dist-hook:
(cd $(top_srcdir); $(HOME)/Projects/FlightGear/admin/am2dsp.pl)
rm -rf `find $(distdir)/projects -name CVS`
#
# Rule to build RPM distribution package

28
NEWS
View File

@@ -1,3 +1,31 @@
New in 0.3.10
* April 5, 2006
* Add a small accessor function to expose local timezone offset.
* Improved exception handling and made output more helpful in various places.
* Better pbuffer runtime detection.
* Add directory creation capability to file/path library.
* Added a basic reference counting class to improve robustness of
memory management in places. Use this for all scenegraph
references, sgmaterial references, sgmatmodel references, and
sgsoundsample references.
* Add support for point sprites.
* Updates to rain cone rendering.
* Add a new vector library and integrate that with improved coordinate
system conversion code.
* Mutex locking and cleanup improvements in the threading abstraction
library.
* Add MacOS RenderTexture support.
* Add a Nasal based io libarary that is not activated by default.
* Added a set of MS-VC8 project files.
* Various platform related bug fixes.
* Various compiler related bug/warning fixes.
* Clean up some things that triggered valgrind warnings.
* Fix a Nasal cmp() bug.
* Removed ancient version of zlib from distribution.
New in 0.3.9
* November 17, 2005

View File

@@ -1,173 +1,8 @@
For your convenience and allowed by zlib's license terms:
http://www.gzip.org/zlib/zlib_license.html a copy of the zlib source
is bundled with SimGear in $(top_srcdir)/src-libs/. You must have
zlib installed before you can build SimGear.
zlib is prerequisite for compiling SimGear and FlightGear. You can fetch
the latest version of zlib from:
- Most linux distributions have a zlib package. For linux
developers, we recommend ysou install your distributions package
rather than building from source.
http://www.zlib.net
- Cygwin installs zlib automatically.
Most modern unix distributions (and cygwin) come with a version of zlib
already installed or available to install as a package.
- For developers on most other platforms, you will have to build
zlib from source and install it yourself. For your convenience a
tar ball of the zlib source is included with the simgear source
distribution. Untar the zlib source, and follow the included
build and installation instructions.
Once zlib is installed you can return to configuring and building
Simgear.
We now send you to the official zlib README ...
=============================================================================
zlib 1.1.4 is a general purpose data compression library. All the code
is thread safe. The data format used by the zlib library
is described by RFCs (Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
format) and rfc1952.txt (gzip format). These documents are also available in
other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
All functions of the compression library are documented in the file zlib.h
(volunteer to write man pages welcome, contact jloup@gzip.org). A usage
example of the library is given in the file example.c which also tests that
the library is working correctly. Another example is given in the file
minigzip.c. The compression library itself is composed of all source files
except example.c and minigzip.c.
To compile all files and run the test program, follow the instructions
given at the top of Makefile. In short "make test; make install"
should work for most machines. For Unix: "./configure; make test; make install"
For MSDOS, use one of the special makefiles such as Makefile.msc.
For VMS, use Make_vms.com or descrip.mms.
Questions about zlib should be sent to <zlib@gzip.org>, or to
Gilles Vollant <info@winimage.com> for the Windows DLL version.
The zlib home page is http://www.zlib.org or http://www.gzip.org/zlib/
Before reporting a problem, please check this site to verify that
you have the latest version of zlib; otherwise get the latest version and
check whether the problem still exists or not.
PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html
before asking for help.
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available in
http://dogma.net/markn/articles/zlibtool/zlibtool.htm
The changes made in version 1.1.4 are documented in the file ChangeLog.
The only changes made since 1.1.3 are bug corrections:
- ZFREE was repeated on same allocation on some error conditions.
This creates a security problem described in
http://www.zlib.org/advisory-2002-03-11.txt
- Returned incorrect error (Z_MEM_ERROR) on some invalid data
- Avoid accesses before window for invalid distances with inflate window
less than 32K.
- force windowBits > 8 to avoid a bug in the encoder for a window size
of 256 bytes. (A complete fix will be available in 1.1.5).
The beta version 1.1.5beta includes many more changes. A new official
version 1.1.5 will be released as soon as extensive testing has been
completed on it.
Unsupported third party contributions are provided in directory "contrib".
A Java implementation of zlib is available in the Java Development Kit
http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
See the zlib home page http://www.zlib.org for details.
A Perl interface to zlib written by Paul Marquess <pmarquess@bfsec.bt.co.uk>
is in the CPAN (Comprehensive Perl Archive Network) sites
http://www.cpan.org/modules/by-module/Compress/
A Python interface to zlib written by A.M. Kuchling <amk@magnet.com>
is available in Python 1.5 and later versions, see
http://www.python.org/doc/lib/module-zlib.html
A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com>
is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
An experimental package to read and write files in .zip format,
written on top of zlib by Gilles Vollant <info@winimage.com>, is
available at http://www.winimage.com/zLibDll/unzip.html
and also in the contrib/minizip directory of zlib.
Notes for some targets:
- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
The zlib DLL support was initially done by Alessandro Iacopetti and is
now maintained by Gilles Vollant <info@winimage.com>. Check the zlib DLL
home page at http://www.winimage.com/zLibDll
From Visual Basic, you can call the DLL functions which do not take
a structure as argument: compress, uncompress and all gz* functions.
See contrib/visual-basic.txt for more information, or get
http://www.tcfb.com/dowseware/cmp-z-it.zip
- For 64-bit Irix, deflate.c must be compiled without any optimization.
With -O, one libpng test fails. The test works in 32 bit mode (with
the -n32 compiler flag). The compiler bug has been reported to SGI.
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1
it works when compiled with cc.
- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1
is necessary to get gzprintf working correctly. This is done by configure.
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works
with other compilers. Use "make test" to check your compiler.
- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
- For Turbo C the small model is supported only with reduced performance to
avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
- For PalmOs, see http://www.cs.uit.no/~perm/PASTA/pilot/software.html
Per Harald Myrvang <perm@stud.cs.uit.no>
Acknowledgments:
The deflate format used by zlib was defined by Phil Katz. The deflate
and zlib specifications were written by L. Peter Deutsch. Thanks to all the
people who reported problems and suggested various improvements in zlib;
they are too numerous to cite here.
Copyright notice:
(C) 1995-2002 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
If you use the zlib library in a product, we would appreciate *not*
receiving lengthy legal documents to sign. The sources are provided
for free but without warranty of any kind. The library has been
entirely written by Jean-loup Gailly and Mark Adler; it does not
include third-party code.
If you redistribute modified sources, we would appreciate that you include
in the file ChangeLog history information documenting your changes.

View File

@@ -35,7 +35,7 @@ RSC=rc.exe
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_MBCS" /FD /c /MT /I "." /I ".." /I ".\SimGear" /I ".\SimGear\metakit-2.4.3\include" /I "..\SimGear\zlib-1.1.4" /D "HAVE_CONFIG_H"
# ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_MBCS" /FD /c /MT /I "." /I ".." /I ".\SimGear" /I "..\zlib-1.2.3" /I "..\OpenAL 1.0 Software Development Kit\include" /D "_USE_MATH_DEFINES" /D "_CRT_SECURE_NO_DEPRECATE" /D "HAVE_CONFIG_H"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
@@ -51,7 +51,7 @@ LINK32=link.exe -lib
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD CPP /nologo /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /FR /FD /GZ /c /MT /I "." /I ".." /I ".\SimGear" /I ".\SimGear\metakit-2.4.3\include" /I "..\SimGear\zlib-1.1.4" /D "HAVE_CONFIG_H"
# ADD CPP /nologo /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_MBCS" /FR /FD /GZ /c /MTd /I "." /I ".." /I ".\SimGear" /I "..\zlib-1.2.3" /I "..\OpenAL 1.0 Software Development Kit\include" /D "_USE_MATH_DEFINES" /D "_CRT_SECURE_NO_DEPRECATE" /D "HAVE_CONFIG_H"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
@@ -556,7 +556,7 @@ SOURCE=.\simgear\math\vector.cxx
# End Source File
# Begin Source File
SOURCE=.\simgear\math\fastmath.cxx
SOURCE=.\simgear\math\SGGeodesy.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
@@ -853,6 +853,51 @@ SOURCE=.\simgear\nasal\mathlib.c
# End Source File
# Begin Source File
SOURCE=.\simgear\nasal\iolib.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgnasal"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\nasal\iolib.h
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgnasal"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\nasal\bitslib.c
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgnasal"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgnasal"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\nasal\misc.c
!IF "$(CFG)" == "SimGear - Win32 Release"
@@ -1124,21 +1169,6 @@ SOURCE=.\simgear\scene\model\animation.cxx
# End Source File
# Begin Source File
SOURCE=.\simgear\scene\model\custtrans.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgmodel"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgmodel"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\scene\model\location.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
@@ -1184,7 +1214,7 @@ SOURCE=.\simgear\scene\model\modellib.cxx
# End Source File
# Begin Source File
SOURCE=.\simgear\scene\model\personality.cxx
SOURCE=.\simgear\scene\model\persparam.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
@@ -1229,7 +1259,7 @@ SOURCE=.\simgear\scene\model\placementtrans.cxx
# End Source File
# Begin Source File
SOURCE=.\simgear\scene\model\shadowvolume.cxx
SOURCE=.\simgear\scene\model\shadanim.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
@@ -1244,7 +1274,7 @@ SOURCE=.\simgear\scene\model\shadowvolume.cxx
# End Source File
# Begin Source File
SOURCE=.\simgear\scene\model\shadanim.cxx
SOURCE=.\simgear\scene\model\SGMaterialAnimation.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
@@ -1489,6 +1519,40 @@ SOURCE=.\simgear\scene\tgdb\userdata.cxx
!ENDIF
# End Source File
# End Group
# Begin Group "Lib_sgutil"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\simgear\scene\util\SGStateAttributeVisitor.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgutil"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgutil"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\scene\util\SGTextureStateAttributeVisitor.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgutil"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgutil"
!ENDIF
# End Source File
# End Group
# Begin Group "Lib_sgscreen"
@@ -1745,6 +1809,36 @@ SOURCE=.\simgear\structure\subsystem_mgr.cxx
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\structure\SGAtomic.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgstructure"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgstructure"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\simgear\structure\SGBinding.cxx
!IF "$(CFG)" == "SimGear - Win32 Release"
# PROP Intermediate_Dir "Release\Lib_sgstructure"
!ELSEIF "$(CFG)" == "SimGear - Win32 Debug"
# PROP Intermediate_Dir "Debug\Lib_sgstructure"
!ENDIF
# End Source File
# End Group
# Begin Group "Lib_sgtiming"

View File

@@ -15,30 +15,6 @@ Package=<4>
###############################################################################
Project: "mklib"=".\SimGear\metakit-2.4.3\win\msvc60\mklib.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "zlib"=".\SimGear\zlib.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>

21
Thanks
View File

@@ -47,6 +47,18 @@ Jean-Francois Doue
http://www.animats.com/simpleppp/ftp/public_html/topics/developers.html
Melchior Franz
METAR parser and fetcher. "material" animation (based on Jim Wilsons's
"emission" animation). Debugging and extension of property listener
features. Addition of removeChildren.
Mathias Froehlich
Reworked and cleaned up large parts of the infrastructure, of math
files, animations and rendering in preparation of a transition to
the OSG library. Added new handlers for shared and referenced objects.
Bruce Finney <bfinney@gte.net>
MSVC5 compatibility.
@@ -71,6 +83,10 @@ Bruce Jackson of NASA <e.b.jackson@larc.nasa.gov>
http://dcb.larc.nasa.gov/www/DCBStaff/ebj/ebj.html
Maik Justus
Fixed an old bug in the SGPropertyNode class.
Richard Kaszeta <bofh@me.umn.edu>
Contributed screen buffer to ppm screen shot routine.
Rich has also helped in the early development of the Flight Gear "altitude
@@ -90,6 +106,11 @@ David Megginson <david@megginson.com>
SimGear property manager/registry
Tim Moore
Ported the (chrome) "shader" animation to OSG, and helped with porting
the "material" animation.
Curt Olson http://www.flightgear.org/~curt/
Curt is responsible for overall project and source code management.
He has his hands in many of the areas.

View File

@@ -4,14 +4,13 @@ exclude_dir = threads
include_path = .
include_path = ..
include_path = .\SimGear
include_path = .\SimGear\metakit-2.4.3\include
include_path = ..\SimGear\zlib-1.1.4
include_path = ..\zlib-1.2.3
include_path = "..\OpenAL 1.0 Software Development Kit\include"
define = _USE_MATH_DEFINES
define = _CRT_SECURE_NO_DEPRECATE
define = HAVE_CONFIG_H
add_project = .\SimGear\metakit-2.4.3\win\msvc60\mklib.dsp,mklib
add_project = .\SimGear\zlib.dsp,zlib
# Rule to create simgear_config.h
add_source_file = SOURCE=.\simgear\simgear_config.h.vc5\
\

View File

@@ -8,7 +8,7 @@ dnl Require at least automake 2.52
AC_PREREQ(2.52)
dnl Initialize the automake stuff
AM_INIT_AUTOMAKE(SimGear, 0.3.9)
AM_INIT_AUTOMAKE(SimGear, 0.3.10)
dnl Specify KAI C++ compiler and flags.
dnl Borrowed with slight modification from blitz distribution.
@@ -119,6 +119,14 @@ if test "x$with_plib" != "x" ; then
EXTRA_DIRS="${EXTRA_DIRS} $with_plib"
fi
# specify the osg location
AC_ARG_WITH(osg, [ --with-osg=PREFIX Specify the prefix path to osg])
if test "x$with_osg" != "x" ; then
echo "osg prefix is $with_osg"
EXTRA_DIRS="${EXTRA_DIRS} $with_osg"
fi
dnl Determine an extra directories to add to include/lib search paths
case "${host}" in
*-apple-darwin* | *-*-cygwin* | *-*-mingw32*)
@@ -250,6 +258,9 @@ case "${host}" in
esac
AC_SEARCH_LIBS(glutGetModifiers, [ glut glut32 freeglut ], have_glut=yes, have_glut=no)
AM_CONDITIONAL(HAVE_GLUT, test "x$have_glut" = "xyes")
opengl_LIBS="$LIBS"
LIBS="$base_LIBS"
@@ -258,10 +269,10 @@ OPENAL_OK="no"
case "${host}" in
*-*-cygwin* | *-*-mingw32*)
dnl CygWin under Windoze.
INCLUDES="$INCLUDES -I/usr/local/include"
INCLUDES="$INCLUDES -I/usr/local/include/"
LIBS="$LIBS -L/usr/local/lib"
AC_SEARCH_LIBS(alGenBuffers, openal32)
AC_SEARCH_LIBS(alutInit, [ openal32 ALut ] )
AC_SEARCH_LIBS(alGenBuffers, [ openal32 openal ] )
AC_SEARCH_LIBS(alutInit, [ openal32 ALut alut ] )
LIBS="$LIBS -lwinmm -ldsound -ldxguid -lole32"
openal_LIBS="$LIBS"
OPENAL_OK="$ac_cv_search_alGenBuffers"
@@ -387,6 +398,7 @@ fi
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
AC_TYPE_MODE_T
AC_HEADER_TIME
AC_STRUCT_TM
@@ -405,7 +417,6 @@ AM_CONFIG_HEADER(simgear/simgear_config.h)
AC_CONFIG_FILES([ \
Makefile \
SimGear.spec \
src-libs/Makefile \
simgear/Makefile \
simgear/version.h \
simgear/compatibility/Makefile \
@@ -427,6 +438,7 @@ AC_CONFIG_FILES([ \
simgear/scene/model/Makefile \
simgear/scene/sky/Makefile \
simgear/scene/tgdb/Makefile \
simgear/scene/util/Makefile \
simgear/screen/Makefile \
simgear/serial/Makefile \
simgear/sound/Makefile \

4
projects/VC7.1/.cvsignore Executable file
View File

@@ -0,0 +1,4 @@
Debug
Release
SimGear.ncb
SimGear.suo

21
projects/VC7.1/SimGear.sln Executable file
View File

@@ -0,0 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimGear", "SimGear.vcproj", "{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Debug.ActiveCfg = Debug|Win32
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Debug.Build.0 = Debug|Win32
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Release.ActiveCfg = Release|Win32
{22540CD3-D3CA-4C86-A773-80AEEE3ACDED}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

1079
projects/VC7.1/SimGear.vcproj Executable file

File diff suppressed because it is too large Load Diff

20
projects/VC8/SimGear.sln Executable file
View File

@@ -0,0 +1,20 @@

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

1348
projects/VC8/SimGear.vcproj Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ endif
# METAR_DIRS =
METAR_DIRS = environment
EXTRA_DIST = simgear_config.h.vc5 version.h.in
EXTRA_DIST = simgear_config.h.vc5 simgear_config.h-msvc71 version.h.in
include_HEADERS = \
compiler.h constants.h sg_inlines.h sg_traits.hxx version.h
@@ -34,4 +34,4 @@ SUBDIRS = \
$(SGTHREAD_DIR) \
timing
DIST_SUBDIRS = $(SUBDIRS) compatibility threads
DIST_SUBDIRS = $(SUBDIRS) compatibility

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/
@@ -45,6 +44,9 @@ SGBucket::SGBucket(const double dlon, const double dlat) {
set_bucket(dlon, dlat);
}
SGBucket::SGBucket(const SGGeod& geod) {
set_bucket(geod);
}
// create an impossible bucket if false
SGBucket::SGBucket(const bool is_good) {
@@ -74,11 +76,6 @@ SGBucket::SGBucket(const long int bindex) {
}
// default destructor
SGBucket::~SGBucket() {
}
// Set the bucket params for the specified lat and lon
void SGBucket::set_bucket( double *lonlat ) {
set_bucket( lonlat[0], lonlat[1] );
@@ -136,6 +133,11 @@ void SGBucket::set_bucket( double dlon, double dlat ) {
}
void SGBucket::set_bucket(const SGGeod& geod)
{
set_bucket(geod.getLongitudeDeg(), geod.getLatitudeDeg());
}
// Build the path name for this bucket
string SGBucket::gen_base_path() const {
// long int index;

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/
@@ -32,6 +31,7 @@
#include <simgear/compiler.h>
#include <simgear/constants.h>
#include <simgear/math/SGMath.hxx>
#ifdef SG_HAVE_STD_INCLUDES
# include <cmath>
@@ -115,10 +115,10 @@ class SGBucket {
private:
double cx, cy; // centerpoint (lon, lat) in degrees of bucket
int lon; // longitude index (-180 to 179)
int lat; // latitude index (-90 to 89)
int x; // x subdivision (0 to 7)
int y; // y subdivision (0 to 7)
short lon; // longitude index (-180 to 179)
short lat; // latitude index (-90 to 89)
char x; // x subdivision (0 to 7)
char y; // y subdivision (0 to 7)
public:
@@ -134,6 +134,13 @@ public:
*/
SGBucket(const double dlon, const double dlat);
/**
* Construct a bucket given a specific location.
* @param dlon longitude specified in degrees
* @param dlat latitude specified in degrees
*/
SGBucket(const SGGeod& geod);
/** Construct a bucket.
* @param is_good if false, create an invalid bucket. This is
* useful * if you are comparing cur_bucket to last_bucket and
@@ -147,11 +154,6 @@ public:
*/
SGBucket(const long int bindex);
/**
* Default destructor.
*/
~SGBucket();
/**
* Reset a bucket to represent a new lat and lon
* @param dlon longitude specified in degrees
@@ -166,6 +168,13 @@ public:
*/
void set_bucket( double *lonlat );
/**
* Reset a bucket to represent a new lat and lon
* @param dlon longitude specified in degrees
* @param dlat latitude specified in degrees
*/
void set_bucket(const SGGeod& geod);
/**
* Create an impossible bucket.
* This is useful if you are comparing cur_bucket to last_bucket
@@ -253,7 +262,24 @@ public:
* @return the height of the tile in meters.
*/
double get_height_m() const;
/**
* @return the center of the bucket in geodetic coordinates.
*/
SGGeod get_center() const
{ return SGGeod::fromDeg(get_center_lon(), get_center_lat()); }
/**
* @return the center of the bucket in geodetic coordinates.
*/
SGGeod get_corner(unsigned num) const
{
double lonFac = ((num + 1) & 2) ? 0.5 : -0.5;
double latFac = ((num ) & 2) ? 0.5 : -0.5;
return SGGeod::fromDeg(get_center_lon() + lonFac*get_width(),
get_center_lat() + latFac*get_height());
}
// Informational methods.
/**

View File

@@ -11,10 +11,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
*
@@ -231,6 +230,7 @@
# define isnan _isnan
# define snprintf _snprintf
# define copysign _copysign
# pragma warning(disable: 4786) // identifier was truncated to '255' characters
# pragma warning(disable: 4244) // conversion from double to float

View File

@@ -14,10 +14,9 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$
@@ -32,9 +31,6 @@
#include <simgear/compiler.h>
#ifdef _MSC_VER
# define _USE_MATH_DEFINES
#endif
#ifdef SG_HAVE_STD_INCLUDES
# include <cmath>
#else
@@ -132,6 +128,12 @@
/** Knots to Miles per second */
#define SG_KT_TO_MPS 0.5144444444444444444
/** Feet per second to Knots */
#define SG_FPS_TO_KT 0.5924838012958962841
/** Knots to Feet per second */
#define SG_KT_TO_FPS 1.6878098571011956874
/** Miles per second to Miles per hour */
#define SG_MPS_TO_MPH 2.2369362920544020312

View File

@@ -14,10 +14,9 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$
@@ -26,6 +25,9 @@
logstream *global_logstream = NULL;
bool logbuf::logging_enabled = true;
#ifdef _MSC_VER
bool logbuf::has_console = true;
#endif
sgDebugClass logbuf::logClass = SG_NONE;
sgDebugPriority logbuf::logPriority = SG_INFO;
streambuf* logbuf::sbuf = NULL;

View File

@@ -16,10 +16,9 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$
@@ -140,6 +139,10 @@ public:
*/
void set_sb( streambuf* sb );
#ifdef _MSC_VER
static void has_no_console() { has_console = false; }
#endif
protected:
/** sync/flush */
@@ -155,6 +158,9 @@ private:
static streambuf* sbuf;
static bool logging_enabled;
#ifdef _MSC_VER
static bool has_console;
#endif
static sgDebugClass logClass;
static sgDebugPriority logPriority;
@@ -185,7 +191,6 @@ inline logbuf::int_type
logbuf::overflow( int c )
{
#ifdef _MSC_VER
static bool has_console = false;
if ( logging_enabled ) {
if ( !has_console ) {
AllocConsole();
@@ -194,7 +199,7 @@ logbuf::overflow( int c )
freopen("conout$", "w", stderr);
has_console = true;
}
sbuf->sputc(c);
return sbuf->sputc(c);
}
else
return EOF == 0 ? 1: 0;

View File

@@ -16,7 +16,7 @@
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
@@ -24,6 +24,9 @@
* @file metar.cxx
* Interface for encoded Meteorological Aerodrome Reports (METAR).
*/
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <string>
#include <time.h>
@@ -107,7 +110,7 @@ SGMetar::SGMetar(const string& m, const string& proxy, const string& port,
scanType();
if (!scanId() || !scanDate()) {
delete[] _data;
throw sg_io_exception("metar data bogus (" + _url + ')');
throw sg_io_exception("metar data bogus ", sg_location(_url));
}
scanModifier();
@@ -133,7 +136,7 @@ SGMetar::SGMetar(const string& m, const string& proxy, const string& port,
if (_grpcount < 4) {
delete[] _data;
throw sg_io_exception("metar data incomplete (" + _url + ')');
throw sg_io_exception("metar data incomplete ", sg_location(_url));
}
_url = "";
@@ -196,7 +199,7 @@ char *SGMetar::loadData(const char *id, const string& proxy, const string& port,
sock->set_timeout(10000);
if (!sock->open(SG_IO_OUT)) {
delete sock;
throw sg_io_exception("cannot connect to " + host);
throw sg_io_exception("cannot connect to ", sg_location(host));
}
string get = "GET ";
@@ -218,7 +221,7 @@ char *SGMetar::loadData(const char *id, const string& proxy, const string& port,
while ((i = sock->readline(buf, buflen))) {
if (i <= 2 && isspace(buf[0]) && (!buf[1] || isspace(buf[1])))
break;
if (!strncmp(buf, "X-MetarProxy: ", 9))
if (!strncmp(buf, "X-MetarProxy: ", 13))
_x_proxy = true;
}
if (i) {
@@ -233,7 +236,8 @@ char *SGMetar::loadData(const char *id, const string& proxy, const string& port,
char *b = buf;
scanBoundary(&b);
if (*b == '<')
throw sg_io_exception("no metar data available from " + _url);
throw sg_io_exception("no metar data available from ",
sg_location(_url));
char *metar = new char[strlen(b) + 2]; // make room for " \0"
strcpy(metar, b);
@@ -608,56 +612,56 @@ bool SGMetar::scanRwyVisRange()
static const struct Token special[] = {
"NSW", "no significant weather",
"VCSH", "showers in the vicinity",
"VCTS", "thunderstorm in the vicinity",
0, 0
{ "NSW", "no significant weather" },
{ "VCSH", "showers in the vicinity" },
{ "VCTS", "thunderstorm in the vicinity" },
{ 0, 0 }
};
static const struct Token description[] = {
"SH", "showers of",
"TS", "thunderstorm with",
"BC", "patches of",
"BL", "blowing",
"DR", "low drifting",
"FZ", "freezing",
"MI", "shallow",
"PR", "partial",
0, 0
{ "SH", "showers of" },
{ "TS", "thunderstorm with" },
{ "BC", "patches of" },
{ "BL", "blowing" },
{ "DR", "low drifting" },
{ "FZ", "freezing" },
{ "MI", "shallow" },
{ "PR", "partial" },
{ 0, 0 }
};
static const struct Token phenomenon[] = {
"DZ", "drizzle",
"GR", "hail",
"GS", "small hail and/or snow pellets",
"IC", "ice crystals",
"PE", "ice pellets",
"RA", "rain",
"SG", "snow grains",
"SN", "snow",
"UP", "unknown precipitation",
"BR", "mist",
"DU", "widespread dust",
"SG", "fog",
"SGBR", "fog bank",
"FU", "smoke",
"HZ", "haze",
"PY", "spray",
"SA", "sand",
"VA", "volcanic ash",
"DS", "duststorm",
"FC", "funnel cloud/tornado waterspout",
"PO", "well-developed dust/sand whirls",
"SQ", "squalls",
"SS", "sandstorm",
"UP", "unknown", // ... due to failed automatic acquisition
0, 0
{ "DZ", "drizzle" },
{ "GR", "hail" },
{ "GS", "small hail and/or snow pellets" },
{ "IC", "ice crystals" },
{ "PE", "ice pellets" },
{ "RA", "rain" },
{ "SG", "snow grains" },
{ "SN", "snow" },
{ "UP", "unknown precipitation" },
{ "BR", "mist" },
{ "DU", "widespread dust" },
{ "FG", "fog" },
{ "FGBR", "fog bank" },
{ "FU", "smoke" },
{ "HZ", "haze" },
{ "PY", "spray" },
{ "SA", "sand" },
{ "VA", "volcanic ash" },
{ "DS", "duststorm" },
{ "FC", "funnel cloud/tornado waterspout" },
{ "PO", "well-developed dust/sand whirls" },
{ "SQ", "squalls" },
{ "SS", "sandstorm" },
{ "UP", "unknown" }, // ... due to failed automatic acquisition
{ 0, 0 }
};
// (+|-|VC)?(NSW|MI|PR|BC|DR|BL|SH|TS|FZ)?((DZ|RA|SN|SG|IC|PE|GR|GS|UP){0,3})(BR|SG|FU|VA|DU|SA|HZ|PY|PO|SQ|FC|SS|DS){0,3}
// (+|-|VC)?(NSW|MI|PR|BC|DR|BL|SH|TS|FZ)?((DZ|RA|SN|SG|IC|PE|GR|GS|UP){0,3})(BR|FG|FU|VA|DU|SA|HZ|PY|PO|SQ|FC|SS|DS){0,3}
bool SGMetar::scanWeather()
{
char *m = _m;
@@ -713,26 +717,26 @@ bool SGMetar::scanWeather()
static const struct Token cloud_types[] = {
"AC", "altocumulus",
"ACC", "altocumulus castellanus",
"ACSL", "altocumulus standing lenticular",
"AS", "altostratus",
"CB", "cumulonimbus",
"CBMAM", "cumulonimbus mammatus",
"CC", "cirrocumulus",
"CCSL", "cirrocumulus standing lenticular",
"CI", "cirrus",
"CS", "cirrostratus",
"CU", "cumulus",
"CUFRA", "cumulus fractus",
"NS", "nimbostratus",
"SAC", "stratoaltocumulus", // guessed
"SC", "stratocumulus",
"SCSL", "stratocumulus standing lenticular",
"ST", "stratus",
"STFRA", "stratus fractus",
"TCU", "towering cumulus",
0, 0
{ "AC", "altocumulus" },
{ "ACC", "altocumulus castellanus" },
{ "ACSL", "altocumulus standing lenticular" },
{ "AS", "altostratus" },
{ "CB", "cumulonimbus" },
{ "CBMAM", "cumulonimbus mammatus" },
{ "CC", "cirrocumulus" },
{ "CCSL", "cirrocumulus standing lenticular" },
{ "CI", "cirrus" },
{ "CS", "cirrostratus" },
{ "CU", "cumulus" },
{ "CUFRA", "cumulus fractus" },
{ "NS", "nimbostratus" },
{ "SAC", "stratoaltocumulus" }, // guessed
{ "SC", "stratocumulus" },
{ "SCSL", "stratocumulus standing lenticular" },
{ "ST", "stratus" },
{ "STFRA", "stratus fractus" },
{ "TCU", "towering cumulus" },
{ 0, 0 }
};
@@ -743,6 +747,14 @@ bool SGMetar::scanSkyCondition()
int i;
SGMetarCloud cl;
if (!strncmp(m, "//////", 6)) {
m += 6;
if (!scanBoundary(&m))
return false;
_m = m;
return true;
}
if (!strncmp(m, "CLR", i = 3) // clear
|| !strncmp(m, "SKC", i = 3) // sky clear
|| !strncmp(m, "NSC", i = 3) // no significant clouds
@@ -832,7 +844,7 @@ bool SGMetar::scanTemperature()
return false;
if (!scanBoundary(&m)) {
if (!strncmp(m, "XX", 2)) // not spec compliant!
m += 2, sign = 0;
m += 2, sign = 0, dew = temp;
else {
sign = 1;
if (*m == 'M')
@@ -957,11 +969,13 @@ bool SGMetar::scanRunwayReport()
m++;
else
return false;
if (*m == '1' || *m == '2' || *m == '5' || *m == '9') { // extent of deposit
r._extent = *m - '0';
r._extent_string = runway_deposit_extent[*m - '0'];
} else if (*m != '/')
return false;
m++;
i = -1;
if (!strncmp(m, "//", 2))
@@ -970,7 +984,7 @@ bool SGMetar::scanRunwayReport()
return false;
if (i == 0)
r._depth = 0.5; // < 1 mm deep (let's say 0.5 :-)
r._depth = 0.0005; // < 1 mm deep (let's say 0.5 :-)
else if (i > 0 && i <= 90)
r._depth = i / 1000.0; // i mm deep
else if (i >= 92 && i <= 98)
@@ -996,6 +1010,7 @@ bool SGMetar::scanRunwayReport()
return false;
_runways[id]._deposit = r._deposit;
_runways[id]._deposit_string = r._deposit_string;
_runways[id]._extent = r._extent;
_runways[id]._extent_string = r._extent_string;
_runways[id]._depth = r._depth;
@@ -1075,13 +1090,13 @@ bool SGMetar::scanTrendForecast()
// (BLU|WHT|GRN|YLO|AMB|RED)
static const struct Token colors[] = {
"BLU", "Blue", // 2500 ft, 8.0 km
"WHT", "White", // 1500 ft, 5.0 km
"GRN", "Green", // 700 ft, 3.7 km
"YLO", "Yellow", // 300 ft, 1.6 km
"AMB", "Amber", // 200 ft, 0.8 km
"RED", "Red", // <200 ft, <0.8 km
0, 0
{ "BLU", "Blue" }, // 2500 ft, 8.0 km
{ "WHT", "White" }, // 1500 ft, 5.0 km
{ "GRN", "Green" }, // 700 ft, 3.7 km
{ "YLO", "Yellow" }, // 300 ft, 1.6 km
{ "AMB", "Amber" }, // 200 ft, 0.8 km
{ "RED", "Red" }, // <200 ft, <0.8 km
{ 0, 0 }
};

View File

@@ -16,7 +16,7 @@
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -1,6 +1,9 @@
// Visual environment helper class
//
// Written by Harald JOHNSEN, started April 2005.
// Minor changes/additions by Vivian Meazza Apr- May 2007
//
// Ported to OSG by Tim Moore Jun 2007
//
// Copyright (C) 2005 Harald JOHNSEN - hjohnsen@evc.net
//
@@ -16,16 +19,16 @@
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <plib/sg.h>
#include <simgear/constants.h>
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/math/point3d.hxx>
@@ -33,6 +36,7 @@
#include <simgear/sound/soundmgr_openal.hxx>
#include <simgear/scene/sky/cloudfield.hxx>
#include <simgear/scene/sky/newcloud.hxx>
#include <simgear/props/props.hxx>
#include "visual_enviro.hxx"
#include <vector>
@@ -50,6 +54,85 @@ typedef struct {
static float rainpos[MAX_RAIN_SLICE];
#define MAX_LT_TREE_SEG 400
#define DFL_MIN_LIGHT 0.35
sgVec3 SGEnviro::min_light = {DFL_MIN_LIGHT, DFL_MIN_LIGHT, DFL_MIN_LIGHT};
#define DFL_STREAK_BRIGHT_NEARMOST_LAYER 0.9
SGfloat SGEnviro::streak_bright_nearmost_layer = DFL_STREAK_BRIGHT_NEARMOST_LAYER;
#define DFL_STREAK_BRIGHT_FARMOST_LAYER 0.5
SGfloat SGEnviro::streak_bright_farmost_layer = DFL_STREAK_BRIGHT_FARMOST_LAYER;
#define DFL_STREAK_PERIOD_MAX 2.5
SGfloat SGEnviro::streak_period_max = DFL_STREAK_PERIOD_MAX;
#define DFL_STREAK_PERIOD_CHANGE_PER_KT 0.005
SGfloat SGEnviro::streak_period_change_per_kt = DFL_STREAK_PERIOD_CHANGE_PER_KT;
#define DFL_STREAK_PERIOD_MIN 1.0
SGfloat SGEnviro::streak_period_min = DFL_STREAK_PERIOD_MIN;
#define DFL_STREAK_LENGTH_MIN 0.03
SGfloat SGEnviro::streak_length_min = DFL_STREAK_LENGTH_MIN;
#define DFL_STREAK_LENGTH_CHANGE_PER_KT 0.0005
SGfloat SGEnviro::streak_length_change_per_kt = DFL_STREAK_LENGTH_CHANGE_PER_KT;
#define DFL_STREAK_LENGTH_MAX 0.1
SGfloat SGEnviro::streak_length_max = DFL_STREAK_LENGTH_MAX;
#define DFL_STREAK_COUNT_MIN 40
int SGEnviro::streak_count_min = DFL_STREAK_COUNT_MIN;
#define DFL_STREAK_COUNT_MAX 190
#if (DFL_STREAK_COUNT_MAX > MAX_RAIN_SLICE)
#error "Bad default!"
#endif
int SGEnviro::streak_count_max = DFL_STREAK_COUNT_MAX;
#define DFL_CONE_BASE_RADIUS 15.0
SGfloat SGEnviro::cone_base_radius = DFL_CONE_BASE_RADIUS;
#define DFL_CONE_HEIGHT 30.0
SGfloat SGEnviro::cone_height = DFL_CONE_HEIGHT;
void SGEnviro::config(const SGPropertyNode* n)
{
if (!n)
return;
const float ml = n->getFloatValue("min-light", DFL_MIN_LIGHT);
sgSetVec3(min_light, ml, ml, ml);
streak_bright_nearmost_layer = n->getFloatValue(
"streak-brightness-nearmost-layer",
DFL_STREAK_BRIGHT_NEARMOST_LAYER);
streak_bright_farmost_layer = n->getFloatValue(
"streak-brightness-farmost-layer",
DFL_STREAK_BRIGHT_FARMOST_LAYER);
streak_period_max = n->getFloatValue(
"streak-period-max",
DFL_STREAK_PERIOD_MAX);
streak_period_min = n->getFloatValue(
"streak-period-min",
DFL_STREAK_PERIOD_MIN);
streak_period_change_per_kt = n->getFloatValue(
"streak-period-change-per-kt",
DFL_STREAK_PERIOD_CHANGE_PER_KT);
streak_length_max = n->getFloatValue(
"streak-length-max",
DFL_STREAK_LENGTH_MAX);
streak_length_min = n->getFloatValue(
"streak-length-min",
DFL_STREAK_LENGTH_MIN);
streak_length_change_per_kt = n->getFloatValue(
"streak-length-change-per-kt",
DFL_STREAK_LENGTH_CHANGE_PER_KT);
streak_count_min = n->getIntValue(
"streak-count-min", DFL_STREAK_COUNT_MIN);
streak_count_max = n->getIntValue(
"streak-count-max", DFL_STREAK_COUNT_MAX);
if (streak_count_max > MAX_RAIN_SLICE)
streak_count_max = MAX_RAIN_SLICE;
cone_base_radius = n->getFloatValue(
"cone-base-radius", DFL_CONE_BASE_RADIUS);
cone_height = n->getFloatValue("cone_height", DFL_CONE_HEIGHT);
}
/**
* A class to render lightnings.
*/
@@ -84,23 +167,23 @@ static list_of_lightning lightnings;
SGEnviro sgEnviro;
SGEnviro::SGEnviro(void) :
SGEnviro::SGEnviro() :
view_in_cloud(false),
turbulence_enable_state(false),
precipitation_enable_state(true),
precipitation_density(100.0),
precipitation_max_alt(0.0),
turbulence_enable_state(false),
last_cloud_turbulence(0.0),
cloud_turbulence(0.0),
lightning_enable_state(false),
elapsed_time(0.0),
dt(0.0),
soundMgr(NULL),
snd_active(false),
snd_dist(0.0),
last_cloud_turbulence(0.0),
cloud_turbulence(0.0),
elapsed_time(0.0),
dt(0.0),
min_time_before_lt(0.0),
fov_width(55.0),
fov_height(55.0),
precipitation_max_alt(0.0),
precipitation_density(100.0)
fov_height(55.0)
{
for(int i = 0; i < MAX_RAIN_SLICE ; i++)
@@ -109,6 +192,8 @@ SGEnviro::SGEnviro(void) :
}
SGEnviro::~SGEnviro(void) {
// OSGFIXME
return;
list_of_lightning::iterator iLightning;
for( iLightning = lightnings.begin() ; iLightning != lightnings.end() ; iLightning++ ) {
delete (*iLightning);
@@ -117,6 +202,8 @@ SGEnviro::~SGEnviro(void) {
}
void SGEnviro::startOfFrame( sgVec3 p, sgVec3 up, double lon, double lat, double alt, double delta_time) {
// OSGFIXME
return;
view_in_cloud = false;
// ask the impostor cache to do some cleanup
if(SGNewCloud::cldCache)
@@ -239,13 +326,15 @@ void SGEnviro::set_lightning_enable_state(bool enable) {
}
void SGEnviro::setLight(sgVec4 adj_fog_color) {
// OSGFIXME
return;
sgCopyVec4( fog_color, adj_fog_color );
if( false ) {
// ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
}
}
void SGEnviro::callback_cloud(float heading, float alt, float radius, int familly, float dist, int cloudId) {
void SGEnviro::callback_cloud(float bearing, float alt, float radius, int family, float dist, int cloudId) {
// send data to wx radar
// compute turbulence
// draw precipitation
@@ -255,7 +344,7 @@ void SGEnviro::callback_cloud(float heading, float alt, float radius, int famill
// http://www.pilotfriend.com/flight_training/weather/THUNDERSTORM%20HAZARDS1.htm
double turbulence = 0.0;
if( dist < radius * radius * 2.25f ) {
switch(familly) {
switch(family) {
case SGNewCloud::CLFamilly_st:
turbulence = 0.2;
break;
@@ -290,7 +379,7 @@ void SGEnviro::callback_cloud(float heading, float alt, float radius, int famill
// convert to LWC for radar (experimental)
// http://www-das.uwyo.edu/~geerts/cwx/notes/chap08/moist_cloud.html
double LWC = 0.0;
switch(familly) {
switch(family) {
case SGNewCloud::CLFamilly_st:
LWC = 0.29;
break;
@@ -317,14 +406,15 @@ void SGEnviro::callback_cloud(float heading, float alt, float radius, int famill
LWC = 0.29*2.0;
break;
}
// add to the list for the wxRadar instrument
if( LWC > 0.0 )
radarEcho.push_back( SGWxRadarEcho ( heading, alt, radius, dist, LWC, false, cloudId ) );
radarEcho.push_back( SGWxRadarEcho ( bearing, alt, radius, dist, 0.0 , LWC, false, cloudId, false ) );
// NB:data valid only from cockpit view
// spawn a new lightning
if(lightning_enable_state && min_time_before_lt <= 0.0 && (familly == SGNewCloud::CLFamilly_cb) &&
if(lightning_enable_state && min_time_before_lt <= 0.0 && (family == SGNewCloud::CLFamilly_cb) &&
dist < 15000.0 * 15000.0 && sg_random() > 0.9f) {
double lat, lon;
Point3D orig, dest;
@@ -332,7 +422,7 @@ void SGEnviro::callback_cloud(float heading, float alt, float radius, int famill
orig.setlon(last_lon * SG_DEGREES_TO_RADIANS );
orig.setelev(0.0);
dist = sgSqrt(dist);
dest = calc_gc_lon_lat(orig, heading, dist);
dest = calc_gc_lon_lat(orig, bearing, dist);
lon = dest.lon() * SG_RADIANS_TO_DEGREES;
lat = dest.lat() * SG_RADIANS_TO_DEGREES;
addLightning( lon, lat, alt );
@@ -343,7 +433,7 @@ void SGEnviro::callback_cloud(float heading, float alt, float radius, int famill
// min_time_before_lt = 5.0;
}
if( (alt - radius * 0.1) > precipitation_max_alt )
switch(familly) {
switch(family) {
case SGNewCloud::CLFamilly_st:
case SGNewCloud::CLFamilly_cu:
case SGNewCloud::CLFamilly_cb:
@@ -360,26 +450,27 @@ list_of_SGWxRadarEcho *SGEnviro::get_radar_echo(void) {
// precipitation rendering code
void SGEnviro::DrawCone2(float baseRadius, float height, int slices, bool down, double rain_norm, double speed) {
// OSGFIXME
return;
sgVec3 light;
sgVec3 min_light = {0.35, 0.35, 0.35};
sgAddVec3( light, fog_color, min_light );
float da = SG_PI * 2.0f / (float) slices;
// low number = faster
float speedf = 2.5f - speed / 200.0;
if( speedf < 1.0f )
speedf = 1.0f;
float lenf = 0.03f + speed / 2000.0;
if( lenf > 0.10f )
lenf = 0.10f;
float speedf = streak_period_max - speed * streak_period_change_per_kt;
if( speedf < streak_period_min )
speedf = streak_period_min;
float lenf = streak_length_min + speed * streak_length_change_per_kt;
if( lenf > streak_length_max )
lenf = streak_length_max;
float t = fmod((float) elapsed_time, speedf) / speedf;
// t = 0.1f;
if( !down )
t = 1.0f - t;
float angle = 0.0f;
glColor4f(1.0f, 0.7f, 0.7f, 0.9f);
//glColor4f(1.0f, 0.7f, 0.7f, 0.9f); // XXX unneeded? overriden below
glBegin(GL_LINES);
int rainpos_indice = 0;
if (slices > MAX_RAIN_SLICE)
slices = MAX_RAIN_SLICE; // should never happen
for( int i = 0 ; i < slices ; i++ ) {
float x = cos(angle) * baseRadius;
float y = sin(angle) * baseRadius;
@@ -387,12 +478,14 @@ void SGEnviro::DrawCone2(float baseRadius, float height, int slices, bool down,
sgVec3 dir = {x, -height, y};
// rain drops at 2 different speed to simulate depth
float t1 = (i & 1 ? t : t + t) + rainpos[rainpos_indice];
float t1 = (i & 1 ? t : t + t) + rainpos[i];
if(t1 > 1.0f) t1 -= 1.0f;
if(t1 > 1.0f) t1 -= 1.0f;
// distant raindrops are more transparent
float c = (i & 1 ? t1 * 0.5f : t1 * 0.9f);
float c = t1 * (i & 1 ?
streak_bright_farmost_layer
: streak_bright_nearmost_layer);
glColor4f(c * light[0], c * light[1], c * light[2], c);
sgVec3 p1, p2;
sgScaleVec3(p1, dir, t1);
@@ -402,13 +495,30 @@ void SGEnviro::DrawCone2(float baseRadius, float height, int slices, bool down,
glVertex3f(p1[0], p1[1] + height, p1[2]);
glVertex3f(p2[0], p2[1] + height, p2[2]);
if( ++rainpos_indice >= MAX_RAIN_SLICE )
rainpos_indice = 0;
}
glEnd();
}
void SGEnviro::drawRain(double pitch, double roll, double heading, double speed, double rain_norm) {
void SGEnviro::drawRain(double pitch, double roll, double heading, double hspeed, double rain_norm) {
// OSGFIXME
return;
#if 0
static int debug_period = 0;
if (debug_period++ == 50) {
debug_period = 0;
cout << "drawRain("
<< pitch << ", "
<< roll << ", "
<< heading << ", "
<< hspeed << ", "
<< rain_norm << ");"
//" angle = " << angle
//<< " raindrop(KTS) = " << raindrop_speed_kts
<< endl;
}
#endif
glBindTexture(GL_TEXTURE_2D, 0);
@@ -419,25 +529,33 @@ void SGEnviro::drawRain(double pitch, double roll, double heading, double speed,
glDisable( GL_FOG );
glDisable(GL_LIGHTING);
int slice_count = (40.0 + rain_norm*150.0)* precipitation_density / 100.0;
int slice_count = static_cast<int>(
(streak_count_min + rain_norm*(streak_count_max-streak_count_min))
* precipitation_density / 100.0);
float angle = speed;
if( angle > 90.0 )
angle = 90.0;
// www.wonderquest.com/falling-raindrops.htm says that
// Raindrop terminal velocity is 5 to 20mph
// Rather than model it accurately (temp, pressure, diameter), and make it
// smaller than terminal when closer to the precipitation cloud base,
// we interpolate in the 5-20mph range according to rain_norm.
double raindrop_speed_kts
= (5.0 + rain_norm*15.0) * SG_MPH_TO_MPS * SG_MPS_TO_KT;
float angle = atanf(hspeed / raindrop_speed_kts) * SG_RADIANS_TO_DEGREES;
glPushMatrix();
// TODO:find the real view orientation, not the AC one
// the cone rotate with speed
// the cone rotate with hspeed
angle = -pitch - angle;
glRotatef(roll, 0.0, 0.0, 1.0);
glRotatef(heading, 0.0, 1.0, 0.0);
glRotatef(angle, 1.0, 0.0, 0.0);
glRotatef(roll, 0.0, 1.0, 0.0);
glRotatef(heading, 0.0, 0.0, 1.0);
// up cone
DrawCone2(15.0, 30.0, slice_count, true, rain_norm, speed);
DrawCone2(cone_base_radius, cone_height,
slice_count, true, rain_norm, hspeed);
// down cone (usually not visible)
if(angle > 0.0 || heading != 0.0)
DrawCone2(15.0, -30.0, slice_count, false, rain_norm, speed);
DrawCone2(cone_base_radius, -cone_height,
slice_count, false, rain_norm, hspeed);
glPopMatrix();
@@ -452,19 +570,21 @@ void SGEnviro::set_soundMgr(SGSoundMgr *mgr) {
soundMgr = mgr;
}
void SGEnviro::drawPrecipitation(double rain_norm, double snow_norm, double hail_norm, double pitch, double roll, double heading, double speed) {
void SGEnviro::drawPrecipitation(double rain_norm, double snow_norm, double hail_norm, double pitch, double roll, double heading, double hspeed) {
// OSGFIXME
return;
if( precipitation_enable_state && rain_norm > 0.0)
if( precipitation_max_alt >= last_alt )
drawRain(pitch, roll, heading, speed, rain_norm);
drawRain(pitch, roll, heading, hspeed, rain_norm);
}
SGLightning::SGLightning(double _lon, double _lat, double _alt) :
nb_tree(0),
lon(_lon),
lat(_lat),
alt(_alt),
age(1.0 + sg_random() * 4.0),
nb_tree(0)
age(1.0 + sg_random() * 4.0)
{
// sequence_count = 1 + sg_random() * 5.0;
lt_build();
@@ -475,6 +595,8 @@ SGLightning::~SGLightning() {
// lightning rendering code
void SGLightning::lt_build_tree_branch(int tree_nr, Point3D &start, float energy, int nbseg, float segsize) {
// OSGFIXME
return;
sgVec3 dir, newdir;
int nseg = 0;
@@ -500,7 +622,7 @@ void SGLightning::lt_build_tree_branch(int tree_nr, Point3D &start, float energy
nseg++;
// add a branch
if( energy * sg_random() > 0.8f )
lt_build_tree_branch(tree_nr + 1, pt, energy * 0.9f, nbseg == 50 ? 10 : nbseg * 0.4f, segsize * 0.7f);
lt_build_tree_branch(tree_nr + 1, pt, energy * 0.9f, nbseg == 50 ? 10 : static_cast<int>(nbseg * 0.4f), segsize * 0.7f);
if( nb_tree >= MAX_LT_TREE_SEG )
return;
@@ -522,6 +644,8 @@ void SGLightning::lt_build_tree_branch(int tree_nr, Point3D &start, float energy
}
void SGLightning::lt_build(void) {
// OSGFIXME
return;
Point3D top;
nb_tree = 0;
top[PX] = 0 ;
@@ -547,6 +671,8 @@ void SGLightning::lt_build(void) {
void SGLightning::lt_Render(void) {
// OSGFIXME
return;
float flash = 0.5;
if( fmod(sgEnviro.elapsed_time*100.0, 100.0) > 50.0 )
flash = sg_random() * 0.75f + 0.25f;
@@ -555,11 +681,12 @@ void SGLightning::lt_Render(void) {
sgVec4 c;
#define DRAW_SEG() \
{glBegin(GL_LINES); \
{glColorMaterial(GL_FRONT, GL_EMISSION); \
glDisable(GL_LINE_SMOOTH); glBegin(GL_LINES); \
glColor4fv(c); \
glVertex3f(lt_tree[n].pt[PX], lt_tree[n].pt[PZ], lt_tree[n].pt[PY]); \
glVertex3f(lt_tree[lt_tree[n].prev].pt[PX], lt_tree[lt_tree[n].prev].pt[PZ], lt_tree[lt_tree[n].prev].pt[PY]); \
glEnd();}
glEnd(); glEnable(GL_LINE_SMOOTH);}
glDepthMask( GL_FALSE );
glEnable(GL_BLEND);
@@ -570,10 +697,12 @@ void SGLightning::lt_Render(void) {
glDisable( GL_FOG );
glPushMatrix();
sgMat4 modelview, tmp;
ssgGetModelviewMatrix( modelview );
// OSGFIXME
// ssgGetModelviewMatrix( modelview );
sgCopyMat4( tmp, sgEnviro.transform );
sgPostMultMat4( tmp, modelview );
ssgLoadModelviewMatrix( tmp );
// OSGFIXME
// ssgLoadModelviewMatrix( tmp );
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 );
@@ -585,7 +714,7 @@ void SGLightning::lt_Render(void) {
glTranslatef( ax, ay, -sgEnviro.last_alt );
sgEnviro.radarEcho.push_back( SGWxRadarEcho ( course, 0.0, 0.0, dist, age, true, 0 ) );
sgEnviro.radarEcho.push_back( SGWxRadarEcho ( course, 0.0, 0.0, dist, 0.0, age, true, 0, false ) );
for( int n = 0 ; n < nb_tree ; n++ ) {
if( lt_tree[n].prev < 0 )
@@ -631,6 +760,8 @@ void SGLightning::lt_Render(void) {
}
void SGEnviro::addLightning(double lon, double lat, double alt) {
// OSGFIXME
return;
if( lightnings.size() > 10)
return;
SGLightning *lt= new SGLightning(lon, lat, alt);
@@ -638,6 +769,8 @@ void SGEnviro::addLightning(double lon, double lat, double alt) {
}
void SGEnviro::drawLightning(void) {
// OSGFIXME
return;
list_of_lightning::iterator iLightning;
// play 'thunder' for lightning
if( snd_active )
@@ -654,7 +787,7 @@ void SGEnviro::drawLightning(void) {
double ax = 0.0, ay = 0.0;
ax = cos(course) * dist;
ay = sin(course) * dist;
SGSoundSample *snd = soundMgr->find("thunder");
SGSharedPtr<SGSoundSample> snd = soundMgr->find("thunder");
if( snd ) {
ALfloat pos[3]={ax, ay, -sgEnviro.last_alt };
snd->set_source_pos(pos);

View File

@@ -1,6 +1,9 @@
// Visual environment helper class
//
// Written by Harald JOHNSEN, started April 2005.
// Minor changes/additions by Vivian Meazza Apr- May 2007
//
// Ported to OSG by Tim Moore Jun 2007
//
// Copyright (C) 2005 Harald JOHNSEN - hjohnsen@evc.net
//
@@ -16,12 +19,14 @@
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//
#ifndef _VISUAL_ENVIRO_HXX
#define _VISUAL_ENVIRO_HXX
#include <plib/sg.h>
#include <simgear/compiler.h>
#include STL_STRING
#include <vector>
@@ -38,23 +43,32 @@ class SGSoundMgr;
*/
class SGWxRadarEcho {
public:
SGWxRadarEcho(float _heading, float _alt, float _radius, float _dist, double _LWC, bool _lightning, int _cloudId) :
SGWxRadarEcho(float _bearing, float _alt, float _radius, float _dist, float _heading,
double _LWC, bool _lightning, int _cloudId, bool _aircraft) :
bearing (_bearing),
heading( _heading ),
alt ( _alt ),
radius ( _radius ),
dist ( _dist ),
LWC ( _LWC ),
lightning ( _lightning ),
aircraft ( _aircraft ),
cloudId ( _cloudId )
{}
/** the heading in radian is versus north */
float heading;
/** the heading and bearing in radian are versus north */
float bearing, heading;
float alt, radius, dist;
/** reflectivity converted to liquid water content. */
double LWC;
/** if true then this data is for a lightning else it is for water echo. */
bool lightning;
/** if true then this data is for an aircraft */
bool aircraft;
/** Unique identifier of cloud */
int cloudId;
};
@@ -90,11 +104,31 @@ private:
/** a list of all the radar echo. */
list_of_SGWxRadarEcho radarEcho;
static sgVec3 min_light;
static SGfloat streak_bright_nearmost_layer,
streak_bright_farmost_layer,
streak_period_max,
streak_period_change_per_kt,
streak_period_min,
streak_length_min,
streak_length_change_per_kt,
streak_length_max;
static int streak_count_min, streak_count_max;
static SGfloat cone_base_radius,
cone_height;
public:
SGEnviro();
~SGEnviro();
/** Read the config from the precipitation rendering config properties.
* @param precip_rendering_cfgNode "/sim/rendering/precipitation" in fg
* Set from whatever info present in the
* subnodes passed, substituting hardwired defaults for missing fields.
* If NULL is given, do nothing.
*/
void config(const class SGPropertyNode* precip_rendering_cfgNode);
/**
* Forward a few states used for renderings.
*/
@@ -107,12 +141,12 @@ public:
* @param heading direction of cloud in radians
* @param alt asl of cloud in meters
* @param radius radius of cloud in meters
* @param familly cloud familly
* @param family cloud family
* @param dist squared dist to cloud in meters
*/
void callback_cloud(float heading, float alt, float radius, int familly, float dist, int cloudId);
void callback_cloud(float heading, float alt, float radius, int family, float dist, int cloudId);
void drawRain(double pitch, double roll, double heading, double speed, double rain_norm);
void drawRain(double pitch, double roll, double heading, double hspeed, double rain_norm);
/**
* Draw rain or snow precipitation around the viewer.
* @param rain_norm rain normalized intensity given by metar class
@@ -120,10 +154,10 @@ public:
* @param hail_norm hail normalized intensity given by metar class
* @param pitch pitch rotation of viewer
* @param roll roll rotation of viewer
* @param speed moving speed of viewer in kt
* @param hspeed moving horizontal speed of viewer in kt
*/
void drawPrecipitation(double rain_norm, double snow_norm, double hail_norm,
double pitch, double roll, double heading, double speed);
double pitch, double roll, double heading, double hspeed);
/**
* Draw the lightnings spawned by cumulo nimbus.
@@ -186,6 +220,12 @@ public:
float get_precipitation_density(void) const;
bool get_precipitation_enable_state(void) const;
/**
* Decrease the precipitation density to the given percentage.
* (Only show the given percentage of rain streaks etc.)
* Default precipitation density upon construction is 100.0.
* @param density 0.0 to 100.0
*/
void set_precipitation_density(float density);
/**
* Enable or disable the rendering of precipitation around the viewer.

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/
@@ -27,9 +26,9 @@
#ifndef _CELESTIALBODY_H_
#define _CELESTIALBODY_H_
#ifndef __cplusplus
#ifndef __cplusplus
# error This library requires C++
#endif
#endif
#include <simgear/constants.h>

View File

@@ -15,10 +15,9 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$
@@ -32,7 +31,7 @@
// Constructor
SGEphemeris::SGEphemeris( const string &path ) {
SGEphemeris::SGEphemeris( const std::string &path ) {
our_sun = new Star;
moon = new MoonPos;
mercury = new Mercury;
@@ -43,9 +42,8 @@ SGEphemeris::SGEphemeris( const string &path ) {
uranus = new Uranus;
neptune = new Neptune;
nplanets = 7;
for ( int i = 0; i < nplanets; ++i ) {
sgdSetVec3( planets[i], 0.0, 0.0, 0.0 );
}
for ( int i = 0; i < nplanets; ++i )
planets[i] = SGVec3d::zeros();
stars = new SGStarData( SGPath(path) );
}

View File

@@ -19,10 +19,9 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$
@@ -30,8 +29,7 @@
#ifndef _EPHEMERIS_HXX
#define _EPHEMERIS_HXX
#include <plib/sg.h>
#include <string>
#include <simgear/ephemeris/star.hxx>
#include <simgear/ephemeris/moonpos.hxx>
@@ -44,6 +42,9 @@
#include <simgear/ephemeris/neptune.hxx>
#include <simgear/ephemeris/stardata.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/misc/sg_path.hxx>
/** Ephemeris class
*
@@ -84,7 +85,7 @@ class SGEphemeris {
// planets[i][1] = Declination
// planets[i][2] = Magnitude
int nplanets;
sgdVec3 planets[7];
SGVec3d planets[7];
SGStarData *stars;
@@ -96,7 +97,7 @@ public:
* calling the constructor you need to provide a path pointing to
* your star database file.
* @param path path to your star database */
SGEphemeris( const string &path );
SGEphemeris( const std::string &path );
/** Destructor */
~SGEphemeris( void );
@@ -156,7 +157,7 @@ public:
* the second is the declination, and the third is the magnitude.
* @return planets array
*/
inline sgdVec3 *getPlanets() { return planets; }
inline SGVec3d *getPlanets() { return planets; }
/** @return the numbers of defined stars. */
inline int getNumStars() const { return stars->getNumStars(); }
@@ -168,7 +169,7 @@ public:
* third is the magnitude.
* @returns star array
*/
inline sgdVec3 *getStars() { return stars->getStars(); }
inline SGVec3d *getStars() { return stars->getStars(); }
};

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -14,10 +14,9 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$
@@ -26,6 +25,7 @@
#endif
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/sgstream.hxx>
#include "stardata.hxx"
@@ -35,16 +35,9 @@
#endif
// Constructor
SGStarData::SGStarData() :
nstars(0)
SGStarData::SGStarData( const SGPath& path )
{
}
SGStarData::SGStarData( SGPath path ) :
nstars(0)
{
data_path = SGPath( path );
load();
load(path);
}
@@ -53,31 +46,28 @@ SGStarData::~SGStarData() {
}
bool SGStarData::load() {
bool SGStarData::load( const SGPath& path ) {
// -dw- avoid local data > 32k error by dynamic allocation of the
// array, problem for some compilers
stars = new sgdVec3[SG_MAX_STARS];
_stars.clear();
// build the full path name to the stars data base file
data_path.append( "stars" );
SG_LOG( SG_ASTRO, SG_INFO, " Loading stars from " << data_path.str() );
// build the full path name to the stars data base file
SGPath tmp = path;
tmp.append( "stars" );
SG_LOG( SG_ASTRO, SG_INFO, " Loading stars from " << tmp.str() );
sg_gzifstream in( data_path.str() );
sg_gzifstream in( tmp.str() );
if ( ! in.is_open() ) {
SG_LOG( SG_ASTRO, SG_ALERT, "Cannot open star file: "
<< data_path.str() );
exit(-1);
<< tmp.str() );
return false;
}
double ra, dec, mag;
char c;
string name;
nstars = 0;
// read in each line of the file
while ( ! in.eof() && nstars < SG_MAX_STARS ) {
while ( ! in.eof() ) {
in >> skipcomment;
getline( in, name, ',' );
@@ -117,13 +107,10 @@ bool SGStarData::load() {
in >> mag;
// cout << " star data = " << ra << " " << dec << " " << mag << endl;
sgdSetVec3( stars[nstars], ra, dec, mag );
++nstars;
_stars.push_back(SGVec3d(ra, dec, mag));
}
SG_LOG( SG_ASTRO, SG_INFO, " Loaded " << nstars << " stars" );
SG_LOG( SG_ASTRO, SG_INFO, " Loaded " << _stars.size() << " stars" );
return true;
}

View File

@@ -14,10 +14,9 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$
@@ -25,37 +24,28 @@
#ifndef _SG_STARDATA_HXX
#define _SG_STARDATA_HXX
#include <vector>
#include <simgear/math/SGMath.hxx>
#include <plib/sg.h>
#include <simgear/misc/sg_path.hxx>
#define SG_MAX_STARS 850
class SGPath;
class SGStarData {
int nstars;
sgdVec3 *stars;
SGPath data_path;
public:
// Constructor
SGStarData();
SGStarData( SGPath path );
SGStarData( const SGPath& path );
// Destructor
~SGStarData();
// load the stars database
bool load();
bool load( const SGPath& path );
// stars
inline int getNumStars() const { return nstars; }
inline sgdVec3 *getStars() { return stars; }
inline int getNumStars() const { return _stars.size(); }
inline SGVec3d *getStars() { return &(_stars[0]); }
private:
std::vector<SGVec3d> _stars;
};

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -15,10 +15,9 @@
* 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 Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* 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.
*
* $Id$
**************************************************************************/

View File

@@ -37,14 +37,14 @@ int main( int argc, char **argv ) {
obj.get_gbs_radius());
cout << endl;
point_list nodes = obj.get_wgs84_nodes();
std::vector<SGVec3d> nodes = obj.get_wgs84_nodes();
cout << "# vertex list" << endl;
for ( i = 0; i < (int)nodes.size(); ++i ) {
printf("v %.5f %.5f %.5f\n", nodes[i].x(), nodes[i].y(), nodes[i].z() );
}
cout << endl;
point_list normals = obj.get_normals();
std::vector<SGVec3f> normals = obj.get_normals();
cout << "# vertex normal list" << endl;
for ( i = 0; i < (int)normals.size(); ++i ) {
printf("vn %.5f %.5f %.5f\n",
@@ -52,7 +52,7 @@ int main( int argc, char **argv ) {
}
cout << endl;
point_list texcoords = obj.get_texcoords();
std::vector<SGVec2f> texcoords = obj.get_texcoords();
cout << "# texture coordinate list" << endl;
for ( i = 0; i < (int)texcoords.size(); ++i ) {
printf("vt %.5f %.5f\n",

View File

@@ -16,7 +16,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -19,7 +19,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -18,7 +18,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -18,7 +18,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
//

View File

@@ -16,7 +16,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
//
@@ -36,6 +36,7 @@
#include STL_STRING
#include <simgear/bucket/newbucket.hxx>
#include <simgear/misc/sg_path.hxx>
#include "lowlevel.hxx"
#include "sg_binobj.hxx"
@@ -45,7 +46,7 @@ SG_USING_STD( string );
SG_USING_STD( vector );
enum {
enum sgObjectTypes {
SG_BOUNDING_SPHERE = 0,
SG_VERTEX_LIST = 1,
@@ -58,20 +59,19 @@ enum {
SG_TRIANGLE_FACES = 10,
SG_TRIANGLE_STRIPS = 11,
SG_TRIANGLE_FANS = 12
} sgObjectTypes;
};
enum {
enum sgIndexTypes {
SG_IDX_VERTICES = 0x01,
SG_IDX_NORMALS = 0x02,
SG_IDX_COLORS = 0x04,
SG_IDX_TEXCOORDS = 0x08
} sgIndexTypes;
};
enum {
enum sgPropertyTypes {
SG_MATERIAL = 0,
SG_INDEX_TYPES = 1
} sgPropertyTypes;
};
class sgSimpleBuffer {
@@ -174,7 +174,7 @@ static void read_object( gzFile fp,
int idx_size;
bool do_vertices, do_normals, do_colors, do_texcoords;
int j, k, idx;
static sgSimpleBuffer buf( 32768 ); // 32 Kb
sgSimpleBuffer buf( 32768 ); // 32 Kb
char material[256];
// default values
@@ -280,13 +280,13 @@ static void read_object( gzFile fp,
// read a binary file and populate the provided structures.
bool SGBinObject::read_bin( const string& file ) {
Point3D p;
SGVec3d p;
int i, j, k;
unsigned int nbytes;
static sgSimpleBuffer buf( 32768 ); // 32 Kb
sgSimpleBuffer buf( 32768 ); // 32 Kb
// zero out structures
gbs_center = Point3D( 0 );
gbs_center = SGVec3d(0, 0, 0);
gbs_radius = 0.0;
wgs84_nodes.clear();
@@ -322,7 +322,7 @@ bool SGBinObject::read_bin( const string& file ) {
string filegz = file + ".gz";
if ( (fp = gzopen( filegz.c_str(), "rb" )) == NULL ) {
SG_LOG( SG_EVENT, SG_ALERT,
"ERROR: opening " << file << " or " << filegz << "for reading!");
"ERROR: opening " << file << " or " << filegz << " for reading!");
return false;
}
@@ -407,7 +407,7 @@ bool SGBinObject::read_bin( const string& file ) {
sgEndianSwap( (uint64_t *)&(dptr[1]) );
sgEndianSwap( (uint64_t *)&(dptr[2]) );
}
gbs_center = Point3D( dptr[0], dptr[1], dptr[2] );
gbs_center = SGVec3d( dptr[0], dptr[1], dptr[2] );
// cout << "Center = " << gbs_center << endl;
ptr += sizeof(double) * 3;
@@ -447,7 +447,7 @@ bool SGBinObject::read_bin( const string& file ) {
sgEndianSwap( (uint32_t *)&(fptr[1]) );
sgEndianSwap( (uint32_t *)&(fptr[2]) );
}
wgs84_nodes.push_back( Point3D(fptr[0], fptr[1], fptr[2]) );
wgs84_nodes.push_back( SGVec3d(fptr[0], fptr[1], fptr[2]) );
fptr += 3;
}
}
@@ -481,7 +481,8 @@ bool SGBinObject::read_bin( const string& file ) {
sgEndianSwap( (uint32_t *)&(fptr[2]) );
sgEndianSwap( (uint32_t *)&(fptr[3]) );
}
colors.push_back( Point3D( fptr[0], fptr[1], fptr[2] ) );
SGVec4f color( fptr[0], fptr[1], fptr[2], fptr[3] );
colors.push_back( color );
fptr += 4;
}
}
@@ -508,14 +509,11 @@ bool SGBinObject::read_bin( const string& file ) {
int count = nbytes / 3;
normals.reserve( count );
for ( k = 0; k < count; ++k ) {
sgdVec3 normal;
sgdSetVec3( normal,
(ptr[0]) / 127.5 - 1.0,
(ptr[1]) / 127.5 - 1.0,
(ptr[2]) / 127.5 - 1.0 );
sgdNormalizeVec3( normal );
SGVec3f normal((ptr[0]) / 127.5 - 1.0,
(ptr[1]) / 127.5 - 1.0,
(ptr[2]) / 127.5 - 1.0);
normals.push_back(Point3D(normal[0], normal[1], normal[2]));
normals.push_back(normalize(normal));
ptr += 3;
}
}
@@ -547,7 +545,7 @@ bool SGBinObject::read_bin( const string& file ) {
sgEndianSwap( (uint32_t *)&(fptr[0]) );
sgEndianSwap( (uint32_t *)&(fptr[1]) );
}
texcoords.push_back( Point3D( fptr[0], fptr[1], 0 ) );
texcoords.push_back( SGVec2f( fptr[0], fptr[1] ) );
fptr += 2;
}
}
@@ -612,28 +610,17 @@ bool SGBinObject::read_bin( const string& file ) {
bool SGBinObject::write_bin( const string& base, const string& name,
const SGBucket& b )
{
Point3D p;
sgVec2 t;
sgVec3 pt;
sgVec4 color;
int i, j;
unsigned char idx_mask;
int idx_size;
string dir = base + "/" + b.gen_base_path();
string command = "mkdir -p " + dir;
#if defined(_MSC_VER) || defined(__MINGW32__)
system( (string("mkdir ") + dir).c_str() );
#else
system(command.c_str());
#endif
string file = dir + "/" + name + ".gz";
cout << "Output file = " << file << endl;
SGPath file = base + "/" + b.gen_base_path() + "/" + name + ".gz";
file.create_dir( 0755 );
cout << "Output file = " << file.str() << endl;
gzFile fp;
if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
cout << "ERROR: opening " << file << " for writing!" << endl;
cout << "ERROR: opening " << file.str() << " for writing!" << endl;
return false;
}
@@ -745,9 +732,8 @@ bool SGBinObject::write_bin( const string& base, const string& name,
sgWriteShort( fp, 1 ); // nelements
sgWriteUInt( fp, wgs84_nodes.size() * sizeof(float) * 3 ); // nbytes
for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
p = wgs84_nodes[i] - gbs_center;
sgSetVec3( pt, p.x(), p.y(), p.z() );
sgWriteVec3( fp, pt );
SGVec3f p = toVec3f(wgs84_nodes[i] - gbs_center);
sgWriteVec3( fp, p.data() );
}
// dump vertex color list
@@ -756,12 +742,7 @@ bool SGBinObject::write_bin( const string& base, const string& name,
sgWriteShort( fp, 1 ); // nelements
sgWriteUInt( fp, colors.size() * sizeof(float) * 4 ); // nbytes
for ( i = 0; i < (int)colors.size(); ++i ) {
p = colors[i];
// Right now we have a place holder for color alpha but we
// need to update the interface so the calling program can
// provide the info.
sgSetVec4( color, p.x(), p.y(), p.z(), 1.0 );
sgWriteVec4( fp, color );
sgWriteVec4( fp, colors[i].data() );
}
// dump vertex normal list
@@ -771,7 +752,7 @@ bool SGBinObject::write_bin( const string& base, const string& name,
sgWriteUInt( fp, normals.size() * 3 ); // nbytes
char normal[3];
for ( i = 0; i < (int)normals.size(); ++i ) {
p = normals[i];
SGVec3f p = normals[i];
normal[0] = (unsigned char)((p.x() + 1.0) * 127.5);
normal[1] = (unsigned char)((p.y() + 1.0) * 127.5);
normal[2] = (unsigned char)((p.z() + 1.0) * 127.5);
@@ -784,9 +765,7 @@ bool SGBinObject::write_bin( const string& base, const string& name,
sgWriteShort( fp, 1 ); // nelements
sgWriteUInt( fp, texcoords.size() * sizeof(float) * 2 ); // nbytes
for ( i = 0; i < (int)texcoords.size(); ++i ) {
p = texcoords[i];
sgSetVec2( t, p.x(), p.y() );
sgWriteVec2( fp, t );
sgWriteVec2( fp, texcoords[i].data() );
}
// dump point groups if they exist
@@ -858,7 +837,8 @@ bool SGBinObject::write_bin( const string& base, const string& name,
// find next group
material = tri_materials[start];
while ( (end < (int)tri_materials.size()) &&
(material == tri_materials[end]) )
(material == tri_materials[end]) &&
3*(end-start) < 32760 )
{
// cout << "end = " << end << endl;
end++;
@@ -1048,24 +1028,15 @@ bool SGBinObject::write_bin( const string& base, const string& name,
bool SGBinObject::write_ascii( const string& base, const string& name,
const SGBucket& b )
{
Point3D p;
int i, j;
string dir = base + "/" + b.gen_base_path();
string command = "mkdir -p " + dir;
#if defined(_MSC_VER) || defined(__MINGW32__)
system( (string("mkdir ") + dir).c_str() );
#else
system(command.c_str());
#endif
// string file = dir + "/" + b.gen_index_str();
string file = dir + "/" + name;
cout << "Output file = " << file << endl;
SGPath file = base + "/" + b.gen_base_path() + "/" + name;
file.create_dir( 0755 );
cout << "Output file = " << file.str() << endl;
FILE *fp;
if ( (fp = fopen( file.c_str(), "w" )) == NULL ) {
cout << "ERROR: opening " << file << " for writing!" << endl;
cout << "ERROR: opening " << file.str() << " for writing!" << endl;
return false;
}
@@ -1098,7 +1069,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
// dump vertex list
fprintf(fp, "# vertex list\n");
for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
p = wgs84_nodes[i] - gbs_center;
SGVec3d p = wgs84_nodes[i] - gbs_center;
fprintf(fp, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
}
@@ -1106,7 +1077,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
fprintf(fp, "# vertex normal list\n");
for ( i = 0; i < (int)normals.size(); ++i ) {
p = normals[i];
SGVec3f p = normals[i];
fprintf(fp, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
}
fprintf(fp, "\n");
@@ -1114,7 +1085,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
// dump texture coordinates
fprintf(fp, "# texture coordinate list\n");
for ( i = 0; i < (int)texcoords.size(); ++i ) {
p = texcoords[i];
SGVec2f p = texcoords[i];
fprintf(fp, "vt %.5f %.5f\n", p.x(), p.y() );
}
fprintf(fp, "\n");
@@ -1140,13 +1111,13 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
// make a list of points for the group
point_list group_nodes;
group_nodes.clear();
Point3D bs_center;
SGVec3d bs_center;
double bs_radius = 0;
for ( i = start; i < end; ++i ) {
for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
group_nodes.push_back( wgs84_nodes[ tris_v[i][j] ] );
bs_center = sgCalcCenter( group_nodes );
bs_radius = sgCalcBoundingRadius( bs_center, group_nodes );
group_nodes.push_back( Point3D::fromSGVec3(wgs84_nodes[ tris_v[i][j] ]) );
bs_center = sgCalcCenter( group_nodes ).toSGVec3d();
bs_radius = sgCalcBoundingRadius( Point3D::fromSGVec3(bs_center), group_nodes );
}
}
@@ -1191,13 +1162,13 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
// make a list of points for the group
point_list group_nodes;
group_nodes.clear();
Point3D bs_center;
SGVec3d bs_center;
double bs_radius = 0;
for ( i = start; i < end; ++i ) {
for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
group_nodes.push_back( wgs84_nodes[ strips_v[i][j] ] );
bs_center = sgCalcCenter( group_nodes );
bs_radius = sgCalcBoundingRadius( bs_center, group_nodes );
group_nodes.push_back( Point3D::fromSGVec3(wgs84_nodes[ strips_v[i][j] ]) );
bs_center = sgCalcCenter( group_nodes ).toSGVec3d();
bs_radius = sgCalcBoundingRadius( Point3D::fromSGVec3(bs_center), group_nodes );
}
}
@@ -1224,7 +1195,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
// close the file
fclose(fp);
command = "gzip --force --best " + file;
string command = "gzip --force --best " + file.str();
system(command.c_str());
return true;

View File

@@ -19,7 +19,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
@@ -89,13 +89,13 @@ typedef group_list::const_iterator const_group_list_iterator;
class SGBinObject {
unsigned short version;
Point3D gbs_center;
SGVec3d gbs_center;
float gbs_radius;
point_list wgs84_nodes; // vertex list
point_list colors; // color list
point_list normals; // normal list
point_list texcoords; // texture coordinate list
std::vector<SGVec3d> wgs84_nodes; // vertex list
std::vector<SGVec4f> colors; // color list
std::vector<SGVec3f> normals; // normal list
std::vector<SGVec2f> texcoords; // texture coordinate list
group_list pts_v; // points vertex index
group_list pts_n; // points normal index
@@ -125,23 +125,51 @@ public:
inline unsigned short get_version() const { return version; }
inline const Point3D& get_gbs_center() const { return gbs_center; }
inline void set_gbs_center( const Point3D& p ) { gbs_center = p; }
inline Point3D get_gbs_center() const { return Point3D::fromSGVec3(gbs_center); }
inline void set_gbs_center( const Point3D& p ) { gbs_center = p.toSGVec3d(); }
inline const SGVec3d& get_gbs_center2() const { return gbs_center; }
inline void set_gbs_center( const SGVec3d& p ) { gbs_center = p; }
inline float get_gbs_radius() const { return gbs_radius; }
inline void set_gbs_radius( float r ) { gbs_radius = r; }
inline const point_list& get_wgs84_nodes() const { return wgs84_nodes; }
inline void set_wgs84_nodes( const point_list& n ) { wgs84_nodes = n; }
inline const std::vector<SGVec3d>& get_wgs84_nodes() const
{ return wgs84_nodes; }
inline void set_wgs84_nodes( const std::vector<SGVec3d>& n )
{ wgs84_nodes = n; }
inline void set_wgs84_nodes( const point_list& n )
{
wgs84_nodes.resize(n.size());
for (unsigned i = 0; i < wgs84_nodes.size(); ++i)
wgs84_nodes[i] = n[i].toSGVec3d();
}
inline const point_list& get_colors() const { return colors; }
inline void set_colors( const point_list& c ) { colors = c; }
inline const std::vector<SGVec4f>& get_colors() const { return colors; }
inline void set_colors( const std::vector<SGVec4f>& c ) { colors = c; }
inline void set_colors( const point_list& c )
{
colors.resize(c.size());
for (unsigned i = 0; i < colors.size(); ++i)
colors[i] = SGVec4f(c[i].toSGVec3f(), 1);
}
inline const point_list& get_normals() const { return normals; }
inline void set_normals( const point_list& n ) { normals = n; }
inline const std::vector<SGVec3f>& get_normals() const { return normals; }
inline void set_normals( const std::vector<SGVec3f>& n ) { normals = n; }
inline void set_normals( const point_list& n )
{
normals.resize(n.size());
for (unsigned i = 0; i < normals.size(); ++i)
normals[i] = n[i].toSGVec3f();
}
inline const point_list& get_texcoords() const { return texcoords; }
inline void set_texcoords( const point_list& t ) { texcoords = t; }
inline const std::vector<SGVec2f>& get_texcoords() const { return texcoords; }
inline void set_texcoords( const std::vector<SGVec2f>& t ) { texcoords = t; }
inline void set_texcoords( const point_list& t )
{
texcoords.resize(t.size());
for (unsigned i = 0; i < texcoords.size(); ++i)
texcoords[i] = t[i].toSGVec2f();
}
inline const group_list& get_pts_v() const { return pts_v; }
inline void set_pts_v( const group_list& g ) { pts_v = g; }

View File

@@ -16,7 +16,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -18,7 +18,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -16,7 +16,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -19,7 +19,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -17,10 +17,13 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <simgear/compiler.h>

View File

@@ -19,7 +19,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -16,7 +16,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -19,7 +19,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -1,3 +1,7 @@
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <simgear/compiler.h>
#include <unistd.h>

View File

@@ -23,6 +23,19 @@
//
// Put in some bullet-proofing to handle magnetic and geographic poles.
// 3/28/2000 EAW
//
// Updated coefficient arrays to use the current WMM2005 model,
// (valid between 2005.0 and 2010.0)
// Also removed unused variables and corrected earth radii constants
// to the values for WGS84 and WMM2005.
// Reference:
// McLean, S., S. Macmillan, S. Maus, V. Lesur, A.
// Thomson, and D. Dater, December 2004, The
// US/UK World Magnetic Model for 2005-2010,
// NOAA Technical Report NESDIS/NGDC-1.
//
// 25/10/2006 Wim Van Hoydonck -- wim.van.hoydonck@gmail.com
//
// The routine uses a spherical harmonic expansion of the magnetic
// potential up to twelfth order, together with its time variation, as
@@ -57,10 +70,9 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$
@@ -76,74 +88,72 @@
static const double pi = 3.14159265358979;
static const double a = 6378.16; /* major radius (km) IAU66 ellipsoid */
static const double f = 1.0 / 298.25; /* inverse flattening IAU66 ellipsoid */
static const double b = 6378.16 * (1.0 -1.0 / 298.25 );
/* minor radius b=a*(1-f) */
static const double r_0 = 6371.2; /* "mean radius" for spherical harmonic expansion */
static const double a = 6378.137; /* semi-major axis (equatorial radius) of WGS84 ellipsoid */
static const double b = 6356.7523142; /* semi-minor axis referenced to the WGS84 ellipsoid */
static const double r_0 = 6371.2; /* standard Earth magnetic reference radius */
static double gnm_wmm2000[13][13] =
static double gnm_wmm2005[13][13] =
{
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-29616.0, -1722.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-2266.7, 3070.2, 1677.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{1322.4, -2291.5, 1255.9, 724.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{932.1, 786.3, 250.6, -401.5, 106.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-211.9, 351.6, 220.8, -134.5, -168.8, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{73.8, 68.2, 74.1, -163.5, -3.8, 17.1, -85.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{77.4, -73.9, 2.2, 35.7, 7.3, 5.2, 8.4, -1.5, 0.0, 0.0, 0.0, 0.0, 0.0},
{23.3, 7.3, -8.5, -6.6, -16.9, 8.6, 4.9, -7.8, -7.6, 0.0, 0.0, 0.0, 0.0},
{5.7, 8.5, 2.0, -9.8, 7.6, -7.0, -2.0, 9.2, -2.2, -6.6, 0.0, 0.0, 0.0},
{-2.2, -5.7, 1.6, -3.7, -0.6, 4.1, 2.2, 2.2, 4.6, 2.3, 0.1, 0.0, 0.0},
{3.3, -1.1, -2.4, 2.6, -1.3, -1.7, -0.6, 0.4, 0.7, -0.3, 2.3, 4.2, 0.0},
{-1.5, -0.2, -0.3, 0.5, 0.2, 0.9, -1.4, 0.6, -0.6, -1.0, -0.3, 0.3, 0.4},
{-29556.8, -1671.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-2340.6, 3046.9, 1657.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{1335.4, -2305.1, 1246.7, 674.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{919.8, 798.1, 211.3, -379.4, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-227.4, 354.6, 208.7, -136.5, -168.3, -14.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{73.2, 69.7, 76.7, -151.2, -14.9, 14.6, -86.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{80.1, -74.5, -1.4, 38.5, 12.4, 9.5, 5.7, 1.8, 0.0, 0.0, 0.0, 0.0, 0.0},
{24.9, 7.7, -11.6, -6.9, -18.2, 10.0, 9.2, -11.6, -5.2, 0.0, 0.0, 0.0, 0.0},
{5.6, 9.9, 3.5, -7.0, 5.1, -10.8, -1.3, 8.8, -6.7, -9.1, 0.0, 0.0, 0.0},
{-2.3, -6.3, 1.6, -2.6, 0.0, 3.1, 0.4, 2.1, 3.9, -0.1, -2.3, 0.0, 0.0},
{2.8, -1.6, -1.7, 1.7, -0.1, 0.1, -0.7, 0.7, 1.8, 0.0, 1.1, 4.1, 0.0},
{-2.4, -0.4, 0.2, 0.8, -0.3, 1.1, -0.5, 0.4, -0.3, -0.3, -0.1, -0.3, -0.1},
};
static double hnm_wmm2000[13][13]=
static double hnm_wmm2005[13][13]=
{
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 5194.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -2484.8, -467.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -224.7, 293.0, -486.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 273.3, -227.9, 120.9, -302.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 42.0, 173.8, -135.0, -38.6, 105.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -17.4, 61.2, 63.2, -62.9, 0.2, 43.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -62.3, -24.5, 8.9, 23.4, 15.0, -27.6, -7.8, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 12.4, -20.8, 8.4, -21.2, 15.5, 9.1, -15.5, -5.4, 0.0, 0.0, 0.0, 0.0},
{0.0, -20.4, 13.9, 12.0, -6.2, -8.6, 9.4, 5.0, -8.4, 3.2, 0.0, 0.0, 0.0},
{0.0, 0.9, -0.7, 3.9, 4.8, -5.3, -1.0, -2.4, 1.3, -2.3, -6.4, 0.0, 0.0},
{0.0, -1.5, 0.7, -1.1, -2.3, 1.3, -0.6, -2.8, -1.6, -0.1, -1.9, 1.4, 0.0},
{0.0, -1.0, 0.7, 2.2, -2.5, -0.2, 0.0, -0.2, 0.0, 0.2, -0.9, -0.2, 1.0},
{0.0, 5079.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -2594.7, -516.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -199.9, 269.3, -524.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 281.5, -226.0, 145.8, -304.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 42.4, 179.8, -123.0, -19.5, 103.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -20.3, 54.7, 63.6, -63.4, -0.1, 50.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -61.5, -22.4, 7.2, 25.4, 11.0, -26.4, -5.1, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 11.2, -21.0, 9.6, -19.8, 16.1, 7.7, -12.9, -0.2, 0.0, 0.0, 0.0, 0.0},
{0.0, -20.1, 12.9, 12.6, -6.7, -8.1, 8.0, 2.9, -7.9, 6.0, 0.0, 0.0, 0.0},
{0.0, 2.4, 0.2, 4.4, 4.8, -6.5, -1.1, -3.4, -0.8, -2.3, -7.9, 0.0, 0.0},
{0.0, 0.3, 1.2, -0.8, -2.5, 0.9, -0.6, -2.7, -0.9, -1.3, -2.0, -1.2, 0.0},
{0.0, -0.4, 0.3, 2.4, -2.6, 0.6, 0.3, 0.0, 0.0, 0.3, -0.9, -0.4, 0.8},
};
static double gtnm_wmm2000[13][13]=
static double gtnm_wmm2005[13][13]=
{
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{14.7, 11.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-13.6, -0.7, -1.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.3, -4.3, 0.9, -8.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-1.6, 0.9, -7.6, 2.2, -3.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-0.9, -0.2, -2.5, -2.7, -0.9, 1.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{1.2, 0.2, 1.7, 1.6, -0.1, -0.3, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-0.4, -0.8, -0.2, 1.1, 0.4, 0.0, -0.2, -0.2, 0.0, 0.0, 0.0, 0.0, 0.0},
{-0.3, 0.6, -0.8, 0.3, -0.2, 0.5, 0.0, -0.6, 0.1, 0.0, 0.0, 0.0, 0.0},
{8.0, 10.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-15.1, -7.8, -0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.4, -2.6, -1.2, -6.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-2.5, 2.8, -7.0, 6.2, -3.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-2.8, 0.7, -3.2, -1.1, 0.1, -0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{-0.7, 0.4, -0.3, 2.3, -2.1, -0.6, 1.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.2, -0.1, -0.3, 1.1, 0.6, 0.5, -0.4, 0.6, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.1, 0.3, -0.4, 0.3, -0.3, 0.2, 0.4, -0.7, 0.4, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
};
static double htnm_wmm2000[13][13]=
static double htnm_wmm2005[13][13]=
{
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -20.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -21.5, -9.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 6.4, -1.3, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 2.3, 0.7, 3.7, -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 2.1, 2.3, 3.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -0.3, -1.7, -0.9, -1.0, -0.1, 1.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 1.4, 0.2, 0.7, 0.4, -0.3, -0.8, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -0.5, 0.1, -0.2, 0.0, 0.1, -0.1, 0.3, 0.2, 0.0, 0.0, 0.0, 0.0},
{0.0, -20.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -23.2, -14.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 5.0, -7.0, -0.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 2.2, 1.6, 5.8, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 1.7, 2.1, 4.8, -1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -0.6, -1.9, -0.4, -0.5, -0.3, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.6, 0.4, 0.2, 0.3, -0.8, -0.2, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, -0.2, 0.1, 0.3, 0.4, 0.1, -0.2, 0.4, 0.4, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
@@ -187,8 +197,8 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
{
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
int n,m;
/* reference dates */
long date0_wmm2000 = yymmdd_to_julian_days(0,1,1);
/* reference date for current model is 1 januari 2005 */
long date0_wmm2005 = yymmdd_to_julian_days(5,1,1);
double yearfrac,sr,r,theta,c,s,psi,fn,fn_0,B_r,B_theta,B_phi,X,Y,Z;
double sinpsi, cospsi, inv_s;
@@ -273,13 +283,14 @@ double calc_magvar( double lat, double lon, double h, long dat, double* field )
}
}
/* compute gnm, hnm at dat */
/* WMM2000 */
yearfrac = (dat - date0_wmm2000) / 365.25;
/* compute Gauss coefficients gnm and hnm of degree n and order m for the desired time
achieved by adjusting the coefficients at time t0 for linear secular variation */
/* WMM2005 */
yearfrac = (dat - date0_wmm2005) / 365.25;
for ( n = 1; n <= nmax; n++ ) {
for ( m = 0; m <= nmax; m++ ) {
gnm[n][m] = gnm_wmm2000[n][m] + yearfrac * gtnm_wmm2000[n][m];
hnm[n][m] = hnm_wmm2000[n][m] + yearfrac * htnm_wmm2000[n][m];
gnm[n][m] = gnm_wmm2005[n][m] + yearfrac * gtnm_wmm2005[n][m];
hnm[n][m] = hnm_wmm2005[n][m] + yearfrac * htnm_wmm2005[n][m];
}
}
@@ -341,7 +352,7 @@ double SGMagVarOrig( double lat, double lon, double h, long dat, double* field )
/* output field B_r,B_th,B_phi,B_x,B_y,B_z */
int n,m;
/* reference dates */
long date0_wmm2000 = yymmdd_to_julian_days(0,1,1);
long date0_wmm2005 = yymmdd_to_julian_days(5,1,1);
double yearfrac,sr,r,theta,c,s,psi,fn,B_r,B_theta,B_phi,X,Y,Z;
@@ -398,12 +409,12 @@ double SGMagVarOrig( double lat, double lon, double h, long dat, double* field )
}
/* compute gnm, hnm at dat */
/* WMM2000 */
yearfrac = (dat - date0_wmm2000) / 365.25;
/* WMM2005 */
yearfrac = (dat - date0_wmm2005) / 365.25;
for ( n = 1; n <= nmax; n++ ) {
for ( m = 0; m <= nmax; m++ ) {
gnm[n][m] = gnm_wmm2000[n][m] + yearfrac * gtnm_wmm2000[n][m];
hnm[n][m] = hnm_wmm2000[n][m] + yearfrac * htnm_wmm2000[n][m];
gnm[n][m] = gnm_wmm2005[n][m] + yearfrac * gtnm_wmm2005[n][m];
hnm[n][m] = hnm_wmm2005[n][m] + yearfrac * htnm_wmm2005[n][m];
}
}

View File

@@ -26,10 +26,9 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$

View File

@@ -16,7 +16,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$

View File

@@ -19,7 +19,7 @@
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
@@ -28,9 +28,9 @@
#define _MAGVAR_HXX
#ifndef __cplusplus
#ifndef __cplusplus
# error This library requires C++
#endif
#endif
/**

View File

@@ -1,3 +1,4 @@
.deps
Makefile
Makefile.in
SGMathTest

View File

@@ -1,11 +1,19 @@
includedir = @includedir@/math
check_PROGRAMS = SGMathTest SGGeometryTest
TESTS = $(check_PROGRAMS)
SGMathTest_SOURCES = SGMathTest.cxx
SGMathTest_LDADD = libsgmath.a $(base_LIBS)
SGGeometryTest_SOURCES = SGGeometryTest.cxx
SGGeometryTest_LDADD = libsgmath.a $(base_LIBS)
lib_LIBRARIES = libsgmath.a
include_HEADERS = \
interpolater.hxx \
leastsqs.hxx \
localconsts.hxx \
point3d.hxx \
polar3d.hxx \
sg_geodesy.hxx \
@@ -13,9 +21,28 @@ include_HEADERS = \
sg_random.h \
sg_types.hxx \
vector.hxx \
fastmath.hxx
EXTRA_DIST = linintp2.h linintp2.inl sphrintp.h sphrintp.inl
SGBox.hxx \
SGCMath.hxx \
SGGeoc.hxx \
SGGeod.hxx \
SGGeodesy.hxx \
SGGeometry.hxx \
SGGeometryFwd.hxx \
SGIntersect.hxx \
SGLimits.hxx \
SGLineSegment.hxx \
SGMatrix.hxx \
SGMath.hxx \
SGMathFwd.hxx \
SGMisc.hxx \
SGPlane.hxx \
SGQuat.hxx \
SGRay.hxx \
SGSphere.hxx \
SGTriangle.hxx \
SGVec2.hxx \
SGVec3.hxx \
SGVec4.hxx
libsgmath_a_SOURCES = \
interpolater.cxx \
@@ -24,6 +51,6 @@ libsgmath_a_SOURCES = \
sg_geodesy.cxx \
sg_random.c \
vector.cxx \
fastmath.cxx
SGGeodesy.cxx
INCLUDES = -I$(top_srcdir)

107
simgear/math/SGBox.hxx Normal file
View File

@@ -0,0 +1,107 @@
// Copyright (C) 2006 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 SGBox_H
#define SGBox_H
template<typename T>
class SGBox {
public:
SGBox() :
_min(SGLimits<T>::max(), SGLimits<T>::max(), SGLimits<T>::max()),
_max(-SGLimits<T>::max(), -SGLimits<T>::max(), -SGLimits<T>::max())
{ }
void setMin(const SGVec3<T>& min)
{ _min = min; }
const SGVec3<T>& getMin() const
{ return _min; }
void setMax(const SGVec3<T>& max)
{ _max = max; }
const SGVec3<T>& getMax() const
{ return _max; }
// Only works for floating point types
SGVec3<T> getCenter() const
{ return T(0.5)*(_min + _max); }
// Only valid for nonempty boxes
SGVec3<T> getSize() const
{ return _max - _min; }
T getVolume() const
{
if (empty())
return 0;
return (_max[0] - _min[0])*(_max[1] - _min[1])*(_max[2] - _min[2]);
}
const bool empty() const
{ return !valid(); }
bool valid() const
{
if (_max[0] < _min[0])
return false;
if (_max[1] < _min[1])
return false;
if (_max[2] < _min[2])
return false;
return true;
}
void clear()
{
_min[0] = SGLimits<T>::max();
_min[1] = SGLimits<T>::max();
_min[2] = SGLimits<T>::max();
_max[0] = -SGLimits<T>::max();
_max[1] = -SGLimits<T>::max();
_max[2] = -SGLimits<T>::max();
}
void expandBy(const SGVec3<T>& v)
{ _min = min(_min, v); _max = max(_max, v); }
void expandBy(const SGBox<T>& b)
{ _min = min(_min, b._min); _max = max(_max, b._max); }
// Note that this only works if the box is nonmepty
unsigned getBroadestAxis() const
{
SGVec3d 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;
};
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGBox<T>& box)
{ return s << "min = " << box.getMin() << ", max = " << box.getMax(); }
#endif

31
simgear/math/SGCMath.hxx Normal file
View File

@@ -0,0 +1,31 @@
// Copyright (C) 2006 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 SGCMath_H
#define SGCMath_H
#include <simgear/compiler.h>
#ifdef SG_HAVE_STD_INCLUDES
// We have cmath from the standard c++ lib available
#include <cmath>
#else
// We only have math.h with the c89 double functions.
#include <math.h>
#endif
#endif

302
simgear/math/SGGeoc.hxx Normal file
View File

@@ -0,0 +1,302 @@
// Copyright (C) 2006 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 SGGeoc_H
#define SGGeoc_H
#include <simgear/constants.h>
// #define SG_GEOC_NATIVE_DEGREE
/// Class representing a geocentric location
class SGGeoc {
public:
/// Default constructor, initializes the instance to lat = lon = lat = 0
SGGeoc(void);
/// Factory from angular values in radians and radius in ft
static SGGeoc fromRadFt(double lon, double lat, double radius);
/// Factory from angular values in degrees and radius in ft
static SGGeoc fromDegFt(double lon, double lat, double radius);
/// Factory from angular values in radians and radius in m
static SGGeoc fromRadM(double lon, double lat, double radius);
/// Factory from angular values in degrees and radius in m
static SGGeoc fromDegM(double lon, double lat, double radius);
/// 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
static SGGeoc fromCart(const SGVec3<double>& cart);
/// Factory to convert position from a geodetic position
/// Note that this conversion is relatively expensive to compute
static SGGeoc fromGeod(const SGGeod& geod);
/// Return the geocentric longitude in radians
double getLongitudeRad(void) const;
/// Set the geocentric longitude from the argument given in radians
void setLongitudeRad(double lon);
/// Return the geocentric longitude in degrees
double getLongitudeDeg(void) const;
/// Set the geocentric longitude from the argument given in degrees
void setLongitudeDeg(double lon);
/// Return the geocentric latitude in radians
double getLatitudeRad(void) const;
/// Set the geocentric latitude from the argument given in radians
void setLatitudeRad(double lat);
/// Return the geocentric latitude in degrees
double getLatitudeDeg(void) const;
/// Set the geocentric latitude from the argument given in degrees
void setLatitudeDeg(double lat);
/// Return the geocentric radius in meters
double getRadiusM(void) const;
/// Set the geocentric radius from the argument given in meters
void setRadiusM(double radius);
/// Return the geocentric radius in feet
double getRadiusFt(void) const;
/// Set the geocentric radius from the argument given in feet
void setRadiusFt(double radius);
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
SGGeoc(double lon, double lat, double radius);
/// The actual data, angles in degree, radius 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
/// to other representations or compute rotation matrices. But both tasks
/// are computionally intensive anyway and that additional 'toRadian'
/// conversion does not hurt too much
double _lon;
double _lat;
double _radius;
};
inline
SGGeoc::SGGeoc(void) :
_lon(0), _lat(0), _radius(0)
{
}
inline
SGGeoc::SGGeoc(double lon, double lat, double radius) :
_lon(lon), _lat(lat), _radius(radius)
{
}
inline
SGGeoc
SGGeoc::fromRadFt(double lon, double lat, double radius)
{
#ifdef SG_GEOC_NATIVE_DEGREE
return SGGeoc(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
radius*SG_FEET_TO_METER);
#else
return SGGeoc(lon, lat, radius*SG_FEET_TO_METER);
#endif
}
inline
SGGeoc
SGGeoc::fromDegFt(double lon, double lat, double radius)
{
#ifdef SG_GEOC_NATIVE_DEGREE
return SGGeoc(lon, lat, radius*SG_FEET_TO_METER);
#else
return SGGeoc(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
radius*SG_FEET_TO_METER);
#endif
}
inline
SGGeoc
SGGeoc::fromRadM(double lon, double lat, double radius)
{
#ifdef SG_GEOC_NATIVE_DEGREE
return SGGeoc(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
radius);
#else
return SGGeoc(lon, lat, radius);
#endif
}
inline
SGGeoc
SGGeoc::fromDegM(double lon, double lat, double radius)
{
#ifdef SG_GEOC_NATIVE_DEGREE
return SGGeoc(lon, lat, radius);
#else
return SGGeoc(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
radius);
#endif
}
inline
SGGeoc
SGGeoc::fromCart(const SGVec3<double>& cart)
{
SGGeoc geoc;
SGGeodesy::SGCartToGeoc(cart, geoc);
return geoc;
}
inline
SGGeoc
SGGeoc::fromGeod(const SGGeod& geod)
{
SGVec3<double> cart;
SGGeodesy::SGGeodToCart(geod, cart);
SGGeoc geoc;
SGGeodesy::SGCartToGeoc(cart, geoc);
return geoc;
}
inline
double
SGGeoc::getLongitudeRad(void) const
{
#ifdef SG_GEOC_NATIVE_DEGREE
return _lon*SGD_DEGREES_TO_RADIANS;
#else
return _lon;
#endif
}
inline
void
SGGeoc::setLongitudeRad(double lon)
{
#ifdef SG_GEOC_NATIVE_DEGREE
_lon = lon*SGD_RADIANS_TO_DEGREES;
#else
_lon = lon;
#endif
}
inline
double
SGGeoc::getLongitudeDeg(void) const
{
#ifdef SG_GEOC_NATIVE_DEGREE
return _lon;
#else
return _lon*SGD_DEGREES_TO_RADIANS;
#endif
}
inline
void
SGGeoc::setLongitudeDeg(double lon)
{
#ifdef SG_GEOC_NATIVE_DEGREE
_lon = lon;
#else
_lon = lon*SGD_RADIANS_TO_DEGREES;
#endif
}
inline
double
SGGeoc::getLatitudeRad(void) const
{
#ifdef SG_GEOC_NATIVE_DEGREE
return _lat*SGD_DEGREES_TO_RADIANS;
#else
return _lat;
#endif
}
inline
void
SGGeoc::setLatitudeRad(double lat)
{
#ifdef SG_GEOC_NATIVE_DEGREE
_lat = lat*SGD_RADIANS_TO_DEGREES;
#else
_lat = lat;
#endif
}
inline
double
SGGeoc::getLatitudeDeg(void) const
{
#ifdef SG_GEOC_NATIVE_DEGREE
return _lat;
#else
return _lat*SGD_DEGREES_TO_RADIANS;
#endif
}
inline
void
SGGeoc::setLatitudeDeg(double lat)
{
#ifdef SG_GEOC_NATIVE_DEGREE
_lat = lat;
#else
_lat = lat*SGD_RADIANS_TO_DEGREES;
#endif
}
inline
double
SGGeoc::getRadiusM(void) const
{
return _radius;
}
inline
void
SGGeoc::setRadiusM(double radius)
{
_radius = radius;
}
inline
double
SGGeoc::getRadiusFt(void) const
{
return _radius*SG_METER_TO_FEET;
}
inline
void
SGGeoc::setRadiusFt(double radius)
{
_radius = radius*SG_FEET_TO_METER;
}
/// Output to an ostream
template<typename char_type, typename traits_type>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGGeoc& g)
{
return s << "lon = " << g.getLongitudeDeg()
<< ", lat = " << g.getLatitudeDeg()
<< ", radius = " << g.getRadiusM();
}
#endif

329
simgear/math/SGGeod.hxx Normal file
View File

@@ -0,0 +1,329 @@
// Copyright (C) 2006 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 SGGeod_H
#define SGGeod_H
#include <simgear/constants.h>
// #define SG_GEOD_NATIVE_DEGREE
/// Class representing a geodetic location
class SGGeod {
public:
/// Default constructor, initializes the instance to lat = lon = elev = 0
SGGeod(void);
/// Factory from angular values in radians and elevation is 0
static SGGeod fromRad(double lon, double lat);
/// Factory from angular values in degrees and elevation is 0
static SGGeod fromDeg(double lon, double lat);
/// Factory from angular values in radians and elevation in ft
static SGGeod fromRadFt(double lon, double lat, double elevation);
/// Factory from angular values in degrees and elevation in ft
static SGGeod fromDegFt(double lon, double lat, double elevation);
/// Factory from angular values in radians and elevation in m
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 to convert position from a cartesian position assumed to be
/// in wgs84 measured in meters
/// Note that this conversion is relatively expensive to compute
static SGGeod fromCart(const SGVec3<double>& cart);
/// Factory to convert position from a geocentric position
/// Note that this conversion is relatively expensive to compute
static SGGeod fromGeoc(const SGGeoc& geoc);
/// Return the geodetic longitude in radians
double getLongitudeRad(void) const;
/// Set the geodetic longitude from the argument given in radians
void setLongitudeRad(double lon);
/// Return the geodetic longitude in degrees
double getLongitudeDeg(void) const;
/// Set the geodetic longitude from the argument given in degrees
void setLongitudeDeg(double lon);
/// Return the geodetic latitude in radians
double getLatitudeRad(void) const;
/// Set the geodetic latitude from the argument given in radians
void setLatitudeRad(double lat);
/// Return the geodetic latitude in degrees
double getLatitudeDeg(void) const;
/// Set the geodetic latitude from the argument given in degrees
void setLatitudeDeg(double lat);
/// Return the geodetic elevation in meters
double getElevationM(void) const;
/// Set the geodetic elevation from the argument given in meters
void setElevationM(double elevation);
/// Return the geodetic elevation in feet
double getElevationFt(void) const;
/// Set the geodetic elevation from the argument given in feet
void setElevationFt(double elevation);
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
/// 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
/// to other representations or compute rotation matrices. But both tasks
/// are computionally intensive anyway and that additional 'toRadian'
/// conversion does not hurt too much
double _lon;
double _lat;
double _elevation;
};
inline
SGGeod::SGGeod(void) :
_lon(0), _lat(0), _elevation(0)
{
}
inline
SGGeod::SGGeod(double lon, double lat, double elevation) :
_lon(lon), _lat(lat), _elevation(elevation)
{
}
inline
SGGeod
SGGeod::fromRad(double lon, double lat)
{
#ifdef SG_GEOD_NATIVE_DEGREE
return SGGeod(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES, 0);
#else
return SGGeod(lon, lat, 0);
#endif
}
inline
SGGeod
SGGeod::fromDeg(double lon, double lat)
{
#ifdef SG_GEOD_NATIVE_DEGREE
return SGGeod(lon, lat, 0);
#else
return SGGeod(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS, 0);
#endif
}
inline
SGGeod
SGGeod::fromRadFt(double lon, double lat, double elevation)
{
#ifdef SG_GEOD_NATIVE_DEGREE
return SGGeod(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
elevation*SG_FEET_TO_METER);
#else
return SGGeod(lon, lat, elevation*SG_FEET_TO_METER);
#endif
}
inline
SGGeod
SGGeod::fromDegFt(double lon, double lat, double elevation)
{
#ifdef SG_GEOD_NATIVE_DEGREE
return SGGeod(lon, lat, elevation*SG_FEET_TO_METER);
#else
return SGGeod(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
elevation*SG_FEET_TO_METER);
#endif
}
inline
SGGeod
SGGeod::fromRadM(double lon, double lat, double elevation)
{
#ifdef SG_GEOD_NATIVE_DEGREE
return SGGeod(lon*SGD_RADIANS_TO_DEGREES, lat*SGD_RADIANS_TO_DEGREES,
elevation);
#else
return SGGeod(lon, lat, elevation);
#endif
}
inline
SGGeod
SGGeod::fromDegM(double lon, double lat, double elevation)
{
#ifdef SG_GEOD_NATIVE_DEGREE
return SGGeod(lon, lat, elevation);
#else
return SGGeod(lon*SGD_DEGREES_TO_RADIANS, lat*SGD_DEGREES_TO_RADIANS,
elevation);
#endif
}
inline
SGGeod
SGGeod::fromCart(const SGVec3<double>& cart)
{
SGGeod geod;
SGGeodesy::SGCartToGeod(cart, geod);
return geod;
}
inline
SGGeod
SGGeod::fromGeoc(const SGGeoc& geoc)
{
SGVec3<double> cart;
SGGeodesy::SGGeocToCart(geoc, cart);
SGGeod geod;
SGGeodesy::SGCartToGeod(cart, geod);
return geod;
}
inline
double
SGGeod::getLongitudeRad(void) const
{
#ifdef SG_GEOD_NATIVE_DEGREE
return _lon*SGD_DEGREES_TO_RADIANS;
#else
return _lon;
#endif
}
inline
void
SGGeod::setLongitudeRad(double lon)
{
#ifdef SG_GEOD_NATIVE_DEGREE
_lon = lon*SGD_RADIANS_TO_DEGREES;
#else
_lon = lon;
#endif
}
inline
double
SGGeod::getLongitudeDeg(void) const
{
#ifdef SG_GEOD_NATIVE_DEGREE
return _lon;
#else
return _lon*SGD_RADIANS_TO_DEGREES;
#endif
}
inline
void
SGGeod::setLongitudeDeg(double lon)
{
#ifdef SG_GEOD_NATIVE_DEGREE
_lon = lon;
#else
_lon = lon*SGD_DEGREES_TO_RADIANS;
#endif
}
inline
double
SGGeod::getLatitudeRad(void) const
{
#ifdef SG_GEOD_NATIVE_DEGREE
return _lat*SGD_DEGREES_TO_RADIANS;
#else
return _lat;
#endif
}
inline
void
SGGeod::setLatitudeRad(double lat)
{
#ifdef SG_GEOD_NATIVE_DEGREE
_lat = lat*SGD_RADIANS_TO_DEGREES;
#else
_lat = lat;
#endif
}
inline
double
SGGeod::getLatitudeDeg(void) const
{
#ifdef SG_GEOD_NATIVE_DEGREE
return _lat;
#else
return _lat*SGD_RADIANS_TO_DEGREES;
#endif
}
inline
void
SGGeod::setLatitudeDeg(double lat)
{
#ifdef SG_GEOD_NATIVE_DEGREE
_lat = lat;
#else
_lat = lat*SGD_DEGREES_TO_RADIANS;
#endif
}
inline
double
SGGeod::getElevationM(void) const
{
return _elevation;
}
inline
void
SGGeod::setElevationM(double elevation)
{
_elevation = elevation;
}
inline
double
SGGeod::getElevationFt(void) const
{
return _elevation*SG_METER_TO_FEET;
}
inline
void
SGGeod::setElevationFt(double elevation)
{
_elevation = elevation*SG_FEET_TO_METER;
}
/// Output to an ostream
template<typename char_type, typename traits_type>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGGeod& g)
{
return s << "lon = " << g.getLongitudeDeg()
<< "deg, lat = " << g.getLatitudeDeg()
<< "deg, elev = " << g.getElevationM()
<< "m";
}
#endif

157
simgear/math/SGGeodesy.cxx Normal file
View File

@@ -0,0 +1,157 @@
// Copyright (C) 2006 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 <cmath>
#include "SGMath.hxx"
// These are hard numbers from the WGS84 standard. DON'T MODIFY
// unless you want to change the datum.
#define _EQURAD 6378137.0
#define _FLATTENING 298.257223563
// These are derived quantities more useful to the code:
#if 0
#define _SQUASH (1 - 1/_FLATTENING)
#define _STRETCH (1/_SQUASH)
#define _POLRAD (EQURAD * _SQUASH)
#else
// High-precision versions of the above produced with an arbitrary
// precision calculator (the compiler might lose a few bits in the FPU
// operations). These are specified to 81 bits of mantissa, which is
// higher than any FPU known to me:
#define _SQUASH 0.9966471893352525192801545
#define _STRETCH 1.0033640898209764189003079
#define _POLRAD 6356752.3142451794975639668
#endif
// The constants from the WGS84 standard
const double SGGeodesy::EQURAD = _EQURAD;
const double SGGeodesy::iFLATTENING = _FLATTENING;
const double SGGeodesy::SQUASH = _SQUASH;
const double SGGeodesy::STRETCH = _STRETCH;
const double SGGeodesy::POLRAD = _POLRAD;
// additional derived and precomputable ones
// for the geodetic conversion algorithm
#define E2 fabs(1 - _SQUASH*_SQUASH)
static double a = _EQURAD;
static double ra2 = 1/(_EQURAD*_EQURAD);
static double e = sqrt(E2);
static double e2 = E2;
static double e4 = E2*E2;
#undef _EQURAD
#undef _FLATTENING
#undef _SQUASH
#undef _STRETCH
#undef _POLRAD
#undef E2
void
SGGeodesy::SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod)
{
// according to
// H. Vermeille,
// Direct transformation from geocentric to geodetic ccordinates,
// Journal of Geodesy (2002) 76:451-454
double X = cart(0);
double Y = cart(1);
double Z = cart(2);
double XXpYY = X*X+Y*Y;
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);
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);
double w = e2*(u+v-q)/(2*v);
double k = sqrt(u+v+w*w)-w;
double D = k*sqrtXXpYY/(k+e2);
geod.setLongitudeRad(2*atan2(Y, X+sqrtXXpYY));
double sqrtDDpZZ = sqrt(D*D+Z*Z);
geod.setLatitudeRad(2*atan2(Z, D+sqrtDDpZZ));
geod.setElevationM((k+e2-1)*sqrtDDpZZ/k);
}
void
SGGeodesy::SGGeodToCart(const SGGeod& geod, SGVec3<double>& cart)
{
// according to
// H. Vermeille,
// Direct transformation from geocentric to geodetic ccordinates,
// Journal of Geodesy (2002) 76:451-454
double lambda = geod.getLongitudeRad();
double phi = geod.getLatitudeRad();
double h = geod.getElevationM();
double sphi = sin(phi);
double n = a/sqrt(1-e2*sphi*sphi);
double cphi = cos(phi);
double slambda = sin(lambda);
double clambda = cos(lambda);
cart(0) = (h+n)*cphi*clambda;
cart(1) = (h+n)*cphi*slambda;
cart(2) = (h+n-e2*n)*sphi;
}
double
SGGeodesy::SGGeodToSeaLevelRadius(const SGGeod& geod)
{
// this is just a simplified version of the SGGeodToCart function above,
// substitute h = 0, take the 2-norm of the cartesian vector and simplify
double phi = geod.getLatitudeRad();
double sphi = sin(phi);
double sphi2 = sphi*sphi;
return a*sqrt((1 + (e4 - 2*e2)*sphi2)/(1 - e2*sphi2));
}
void
SGGeodesy::SGCartToGeoc(const SGVec3<double>& cart, SGGeoc& geoc)
{
double minVal = SGLimits<double>::min();
if (fabs(cart(0)) < minVal && fabs(cart(1)) < minVal)
geoc.setLongitudeRad(0);
else
geoc.setLongitudeRad(atan2(cart(1), cart(0)));
double nxy = sqrt(cart(0)*cart(0) + cart(1)*cart(1));
if (fabs(nxy) < minVal && fabs(cart(2)) < minVal)
geoc.setLatitudeRad(0);
else
geoc.setLatitudeRad(atan2(cart(2), nxy));
geoc.setRadiusM(norm(cart));
}
void
SGGeodesy::SGGeocToCart(const SGGeoc& geoc, SGVec3<double>& cart)
{
double lat = geoc.getLatitudeRad();
double lon = geoc.getLongitudeRad();
double slat = sin(lat);
double clat = cos(lat);
double slon = sin(lon);
double clon = cos(lon);
cart = geoc.getRadiusM()*SGVec3<double>(clat*clon, clat*slon, slat);
}

View File

@@ -0,0 +1,50 @@
// Copyright (C) 2006 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 SGGeodesy_H
#define SGGeodesy_H
class SGGeodesy {
public:
// Hard numbers from the WGS84 standard.
static const double EQURAD;
static const double iFLATTENING;
static const double SQUASH;
static const double STRETCH;
static const double POLRAD;
/// Takes a cartesian coordinate data and returns the geodetic
/// coordinates.
static void SGCartToGeod(const SGVec3<double>& cart, SGGeod& geod);
/// Takes a geodetic coordinate data and returns the cartesian
/// coordinates.
static void SGGeodToCart(const SGGeod& geod, SGVec3<double>& cart);
/// Takes a geodetic coordinate data and returns the sea level radius.
static double SGGeodToSeaLevelRadius(const SGGeod& geod);
/// Takes a cartesian coordinate data and returns the geocentric
/// coordinates.
static void SGCartToGeoc(const SGVec3<double>& cart, SGGeoc& geoc);
/// Takes a geocentric coordinate data and returns the cartesian
/// coordinates.
static void SGGeocToCart(const SGGeoc& geoc, SGVec3<double>& cart);
};
#endif

View File

@@ -0,0 +1,38 @@
// Copyright (C) 2006 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 SGGeometry_HXX
#define SGGeometry_HXX
// Required ...
#include "SGMath.hxx"
// Make sure all is defined
#include "SGGeometryFwd.hxx"
// Geometric primitives we know about
#include "SGBox.hxx"
#include "SGSphere.hxx"
#include "SGRay.hxx"
#include "SGLineSegment.hxx"
#include "SGPlane.hxx"
#include "SGTriangle.hxx"
// Intersection tests
#include "SGIntersect.hxx"
#endif

View File

@@ -0,0 +1,51 @@
// Copyright (C) 2006 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 SGGeometryFwd_HXX
#define SGGeometryFwd_HXX
template<typename T>
class SGBox;
typedef SGBox<float> SGBoxf;
typedef SGBox<double> SGBoxd;
template<typename T>
class SGSphere;
typedef SGSphere<float> SGSpheref;
typedef SGSphere<double> SGSphered;
template<typename T>
class SGRay;
typedef SGRay<float> SGRayf;
typedef SGRay<double> SGRayd;
template<typename T>
class SGLineSegment;
typedef SGLineSegment<float> SGLineSegmentf;
typedef SGLineSegment<double> SGLineSegmentd;
template<typename T>
class SGPlane;
typedef SGPlane<float> SGPlanef;
typedef SGPlane<double> SGPlaned;
template<typename T>
class SGTriangle;
typedef SGTriangle<float> SGTrianglef;
typedef SGTriangle<double> SGTriangled;
#endif

View File

@@ -0,0 +1,442 @@
// Copyright (C) 2006 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 <cstdlib>
#include <iostream>
#include "SGGeometry.hxx"
#include "sg_random.h"
template<typename T>
SGVec3<T> rndVec3(void)
{
return SGVec3<T>(sg_random(), sg_random(), sg_random());
}
template<typename T>
bool
TriangleLineIntersectionTest(void)
{
unsigned nTests = 100000;
unsigned failedCount = 0;
for (unsigned i = 0; i < nTests; ++i) {
SGVec3<T> v0 = rndVec3<T>();
SGVec3<T> v1 = rndVec3<T>();
SGVec3<T> v2 = rndVec3<T>();
SGTriangle<T> tri(v0, v1, v2);
// generate random coeficients
T u = 4*sg_random() - 2;
T v = 4*sg_random() - 2;
T t = 4*sg_random() - 2;
SGVec3<T> isectpt = v0 + u*(v1 - v0) + v*(v2 - v0);
SGLineSegment<T> lineSegment;
SGVec3<T> dir = rndVec3<T>();
SGVec3<T> isectres;
lineSegment.set(isectpt - t*dir, isectpt + (1 - t)*dir);
if (intersects(isectres, tri, lineSegment)) {
if (0 <= u && 0 <= v && u+v <= 1 && 0 <= t && t <= 1) {
if (!equivalent(isectres, isectpt)) {
std::cout << "Failed line segment intersection test #" << i
<< ": not equivalent!\nu = "
<< u << ", v = " << v << ", t = " << t
<< "\n" << tri << "\n" << lineSegment << std::endl;
++failedCount;
}
} else {
std::cout << "Failed line segment intersection test #" << i
<< ": false positive!\nu = "
<< u << ", v = " << v << ", t = " << t
<< "\n" << tri << "\n" << lineSegment << std::endl;
++failedCount;
}
} else {
if (0 <= u && 0 <= v && u+v <= 1 && 0 <= t && t <= 1) {
std::cout << "Failed line segment intersection test #" << i
<< ": false negative!\nu = "
<< u << ", v = " << v << ", t = " << t
<< "\n" << tri << "\n" << lineSegment << std::endl;
++failedCount;
}
}
SGRay<T> ray;
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)) {
std::cout << "Failed ray intersection test #" << i
<< ": not equivalent!\nu = "
<< u << ", v = " << v << ", t = " << t
<< "\n" << tri << "\n" << ray << std::endl;
++failedCount;
}
} else {
std::cout << "Failed ray intersection test #" << i
<< ": false positive!\nu = "
<< u << ", v = " << v << ", t = " << t
<< "\n" << tri << "\n" << ray << std::endl;
++failedCount;
}
} else {
if (0 <= u && 0 <= v && u+v <= 1 && 0 <= t) {
std::cout << "Failed ray intersection test #" << i
<< ": false negative !\nu = "
<< u << ", v = " << v << ", t = " << t
<< "\n" << tri << "\n" << ray << std::endl;
++failedCount;
}
}
}
if (nTests < 100*failedCount) {
std::cout << "Failed ray intersection tests: " << failedCount
<< " tests out of " << nTests
<< " went wrong. Abort!" << std::endl;
return false;
}
/// Some crude handmade test
SGVec3<T> v0 = SGVec3<T>(0, 0, 0);
SGVec3<T> v1 = SGVec3<T>(1, 0, 0);
SGVec3<T> v2 = SGVec3<T>(0, 1, 0);
SGTriangle<T> tri(v0, v1, v2);
SGRay<T> ray;
ray.set(SGVec3<T>(0, 0, 1), SGVec3<T>(0.1, 0.1, -1));
if (!intersects(tri, ray)) {
std::cout << "Failed test #1!" << std::endl;
return false;
}
ray.set(SGVec3<T>(0, 0, 1), SGVec3<T>(0, 0, -1));
if (!intersects(tri, ray)) {
std::cout << "Failed test #2!" << std::endl;
return false;
}
SGLineSegment<T> lineSegment;
lineSegment.set(SGVec3<T>(0, 0, 1), SGVec3<T>(0.1, 0.1, -1));
if (!intersects(tri, lineSegment)) {
std::cout << "Failed test #3!" << std::endl;
return false;
}
lineSegment.set(SGVec3<T>(0, 0, 1), SGVec3<T>(0, 0, -1));
if (!intersects(tri, lineSegment)) {
std::cout << "Failed test #4!" << std::endl;
return false;
}
lineSegment.set(SGVec3<T>(0, 0, 1), SGVec3<T>(0, 1, -1));
if (!intersects(tri, lineSegment)) {
std::cout << "Failed test #5!" << std::endl;
return false;
}
lineSegment.set(SGVec3<T>(0, 0, 1), SGVec3<T>(1, 0, -1));
if (!intersects(tri, lineSegment)) {
std::cout << "Failed test #6!" << std::endl;
return false;
}
lineSegment.set(SGVec3<T>(0, 0, 1), SGVec3<T>(1, 1, -1));
if (!intersects(tri, lineSegment)) {
std::cout << "Failed test #7!" << std::endl;
return false;
}
// is exactly in the plane
// FIXME: cannot detect that yet ??
// lineSegment.set(SGVec3<T>(0, 0, 0), SGVec3<T>(1, 0, 0));
// if (!intersects(tri, lineSegment)) {
// std::cout << "Failed test #8!" << std::endl;
// return false;
// }
// is exactly in the plane
// FIXME: cannot detect that yet ??
// lineSegment.set(SGVec3<T>(-1, 0, 0), SGVec3<T>(1, 0, 0));
// if (!intersects(tri, lineSegment)) {
// std::cout << "Failed test #9!" << std::endl;
// return false;
// }
// is exactly paralell to the plane
// FIXME: cannot detect that yet ??
// lineSegment.set(SGVec3<T>(-1, 1, 0), SGVec3<T>(1, 1, 0));
// if (intersects(tri, lineSegment)) {
// std::cout << "Failed test #10!" << std::endl;
// return false;
// }
// should fail since the line segment poins slightly beyond the triangle
lineSegment.set(SGVec3<T>(0, 0, 1), SGVec3<T>(1, 1, -0.9));
if (intersects(tri, lineSegment)) {
std::cout << "Failed test #11!" << std::endl;
return false;
}
lineSegment.set(SGVec3<T>(0, 0, 1), SGVec3<T>(0, -0.1, -1));
if (intersects(tri, lineSegment)) {
std::cout << "Failed test #12!" << std::endl;
return false;
}
lineSegment.set(SGVec3<T>(0, 0, 1), SGVec3<T>(-0.1, -0.1, -1));
if (intersects(tri, lineSegment)) {
std::cout << "Failed test #13!" << std::endl;
return false;
}
lineSegment.set(SGVec3<T>(0, 0, 1), SGVec3<T>(-0.1, 0, -1));
if (intersects(tri, lineSegment)) {
std::cout << "Failed test #14!" << std::endl;
return false;
}
return true;
}
template<typename T>
bool
SphereLineIntersectionTest(void)
{
unsigned nTests = 100000;
unsigned failedCount = 0;
for (unsigned i = 0; i < nTests; ++i) {
SGVec3<T> center = rndVec3<T>();
T radius = 2*sg_random();
SGSphere<T> sphere(center, radius);
SGVec3<T> offset = normalize(rndVec3<T>());
T t = 4*sg_random();
// This one is the point we use to judge if the test should fail or not
SGVec3<T> base = center + t*offset;
SGVec3<T> per = perpendicular(offset);
SGVec3<T> start = base + 4*sg_random()*per;
SGVec3<T> end = base - 4*sg_random()*per;
SGLineSegment<T> lineSegment;
lineSegment.set(start, end);
if (intersects(sphere, lineSegment)) {
if (radius < t) {
std::cout << "Failed sphere line intersection test #" << i
<< ": false positive!\nt = " << t << "\n"
<< sphere << "\n" << lineSegment << std::endl;
++failedCount;
}
} else {
if (t <= radius) {
std::cout << "Failed sphere line intersection test #" << i
<< ": false negative!\nt = " << t << "\n"
<< sphere << "\n" << lineSegment << std::endl;
++failedCount;
}
}
SGRay<T> ray;
ray.set(start, end - start);
if (intersects(sphere, ray)) {
if (radius < t) {
std::cout << "Failed sphere line intersection test #" << i
<< ": false positive!\nt = " << t << "\n"
<< sphere << "\n" << ray << std::endl;
++failedCount;
}
} else {
if (t <= radius) {
std::cout << "Failed sphere line intersection test #" << i
<< ": false negative!\nt = " << t << "\n"
<< sphere << "\n" << ray << std::endl;
++failedCount;
}
}
}
if (nTests < 100*failedCount) {
std::cout << "Failed sphere line intersection tests: " << failedCount
<< " tests out of " << nTests
<< " went wrong. Abort!" << std::endl;
return false;
}
failedCount = 0;
for (unsigned i = 0; i < nTests; ++i) {
SGVec3<T> center = rndVec3<T>();
T radius = 2*sg_random();
SGSphere<T> sphere(center, radius);
SGVec3<T> offset = normalize(rndVec3<T>());
T t = 4*sg_random();
// This one is the point we use to judge if the test should fail or not
SGVec3<T> base = center + t*offset;
SGVec3<T> start = base;
SGVec3<T> end = base + 2*sg_random()*offset;
SGLineSegment<T> lineSegment;
lineSegment.set(start, end);
if (intersects(sphere, lineSegment)) {
if (radius < t) {
std::cout << "Failed sphere line intersection test #" << i
<< ": false positive!\nt = " << t << "\n"
<< sphere << "\n" << lineSegment << std::endl;
++failedCount;
}
} else {
if (t <= radius) {
std::cout << "Failed sphere line intersection test #" << i
<< ": false negative!\nt = " << t << "\n"
<< sphere << "\n" << lineSegment << std::endl;
++failedCount;
}
}
SGRay<T> ray;
ray.set(start, end - start);
if (intersects(sphere, ray)) {
if (radius < t) {
std::cout << "Failed sphere line intersection test #" << i
<< ": false positive!\nt = " << t << "\n"
<< sphere << "\n" << ray << std::endl;
++failedCount;
}
} else {
if (t <= radius) {
std::cout << "Failed sphere line intersection test #" << i
<< ": false negative!\nt = " << t << "\n"
<< sphere << "\n" << ray << std::endl;
++failedCount;
}
}
}
if (nTests < 100*failedCount) {
std::cout << "Failed sphere line intersection tests: " << failedCount
<< " tests out of " << nTests
<< " went wrong. Abort!" << std::endl;
return false;
}
return true;
}
template<typename T>
bool
BoxLineIntersectionTest(void)
{
// ok, bad test case coverage, but better than nothing ...
unsigned nTests = 100000;
unsigned failedCount = 0;
for (unsigned i = 0; i < nTests; ++i) {
SGBox<T> box;
box.expandBy(rndVec3<T>());
box.expandBy(rndVec3<T>());
SGVec3<T> center = box.getCenter();
// This one is the point we use to judge if the test should fail or not
SGVec3<T> base = rndVec3<T>();
SGVec3<T> dir = base - center;
SGLineSegment<T> lineSegment;
lineSegment.set(base, base + dir);
if (intersects(box, lineSegment)) {
if (!intersects(box, base)) {
std::cout << "Failed box line intersection test #" << i
<< ": false positive!\n"
<< box << "\n" << lineSegment << std::endl;
++failedCount;
}
} else {
if (intersects(box, base)) {
std::cout << "Failed box line intersection test #" << i
<< ": false negative!\n"
<< box << "\n" << lineSegment << std::endl;
++failedCount;
}
}
SGRay<T> ray;
ray.set(base, dir);
if (intersects(box, ray)) {
if (!intersects(box, base)) {
std::cout << "Failed box line intersection test #" << i
<< ": false positive!\n"
<< box << "\n" << ray << std::endl;
++failedCount;
}
} else {
if (intersects(box, base)) {
std::cout << "Failed box line intersection test #" << i
<< ": false negative!\n"
<< box << "\n" << ray << 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;
}
int
main(void)
{
std::cout << "Testing Geometry intersection routines.\n"
<< "Some of these tests can fail due to roundoff problems...\n"
<< "Dont worry if only a few of them fail..." << std::endl;
if (!TriangleLineIntersectionTest<float>())
return EXIT_FAILURE;
if (!TriangleLineIntersectionTest<double>())
return EXIT_FAILURE;
if (!SphereLineIntersectionTest<float>())
return EXIT_FAILURE;
if (!SphereLineIntersectionTest<double>())
return EXIT_FAILURE;
if (!BoxLineIntersectionTest<float>())
return EXIT_FAILURE;
if (!BoxLineIntersectionTest<double>())
return EXIT_FAILURE;
std::cout << "Successfully passed all tests!" << std::endl;
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,627 @@
// Copyright (C) 2006 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 SGIntersect_HXX
#define SGIntersect_HXX
template<typename T>
inline bool
intersects(const SGBox<T>& box, const SGSphere<T>& sphere)
{
if (sphere.empty())
return false;
// Is more or less trivially included in the next tests
// if (box.empty())
// return false;
if (sphere.getCenter().x() < box.getMin().x() - sphere.getRadius())
return false;
if (sphere.getCenter().y() < box.getMin().y() - sphere.getRadius())
return false;
if (sphere.getCenter().z() < box.getMin().z() - sphere.getRadius())
return false;
if (box.getMax().x() + sphere.getRadius() < sphere.getCenter().x())
return false;
if (box.getMax().y() + sphere.getRadius() < sphere.getCenter().y())
return false;
if (box.getMax().z() + sphere.getRadius() < sphere.getCenter().z())
return false;
return true;
}
// make it symmetric
template<typename T>
inline bool
intersects(const SGSphere<T>& sphere, const SGBox<T>& box)
{ return intersects(box, sphere); }
template<typename T>
inline bool
intersects(const SGVec3<T>& v, const SGBox<T>& box)
{
if (v[0] < box.getMin()[0])
return false;
if (box.getMax()[0] < v[0])
return false;
if (v[1] < box.getMin()[1])
return false;
if (box.getMax()[1] < v[1])
return false;
if (v[2] < box.getMin()[2])
return false;
if (box.getMax()[2] < v[2])
return false;
return true;
}
template<typename T>
inline bool
intersects(const SGBox<T>& box, const SGVec3<T>& v)
{ return intersects(v, box); }
template<typename T>
inline bool
intersects(const SGRay<T>& ray, const SGPlane<T>& plane)
{
// We compute the intersection point
// x = origin + \alpha*direction
// from the ray origin and non nomalized direction.
// For 0 <= \alpha the ray intersects the infinite plane.
// The intersection point x can also be written
// x = n*dist + y
// where n is the planes normal, dist is the distance of the plane from
// the origin in normal direction and y is ana aproriate vector
// perpendicular to n.
// Equate the x values and take the scalar product with the plane normal n.
// dot(n, origin) + \alpha*dot(n, direction) = dist
// We can now compute alpha from the above equation.
// \alpha = (dist - dot(n, origin))/dot(n, direction)
// The negative numerator for the \alpha expression
T num = plane.getPositiveDist();
num -= dot(plane.getNormal(), ray.getOrigin());
// If the numerator is zero, we have the rays origin included in the plane
if (fabs(num) <= SGLimits<T>::min())
return true;
// The denominator for the \alpha expression
T den = dot(plane.getNormal(), ray.getDirection());
// If we get here, we already know that the rays origin is not included
// in the plane. Thus if we have a zero denominator we have
// a ray paralell to the plane. That is no intersection.
if (fabs(den) <= SGLimits<T>::min())
return false;
// We would now compute \alpha = num/den and compare with 0 and 1.
// But to avoid that expensive division, check equation multiplied by
// the denominator.
T alphaDen = copysign(1, den)*num;
if (alphaDen < 0)
return false;
return true;
}
// make it symmetric
template<typename T>
inline bool
intersects(const SGPlane<T>& plane, const SGRay<T>& ray)
{ return intersects(ray, plane); }
template<typename T>
inline bool
intersects(SGVec3<T>& dst, const SGRay<T>& ray, const SGPlane<T>& plane)
{
// We compute the intersection point
// x = origin + \alpha*direction
// from the ray origin and non nomalized direction.
// For 0 <= \alpha the ray intersects the infinite plane.
// The intersection point x can also be written
// x = n*dist + y
// where n is the planes normal, dist is the distance of the plane from
// the origin in normal direction and y is ana aproriate vector
// perpendicular to n.
// Equate the x values and take the scalar product with the plane normal n.
// dot(n, origin) + \alpha*dot(n, direction) = dist
// We can now compute alpha from the above equation.
// \alpha = (dist - dot(n, origin))/dot(n, direction)
// The negative numerator for the \alpha expression
T num = plane.getPositiveDist();
num -= dot(plane.getNormal(), ray.getOrigin());
// If the numerator is zero, we have the rays origin included in the plane
if (fabs(num) <= SGLimits<T>::min()) {
dst = ray.getOrigin();
return true;
}
// The denominator for the \alpha expression
T den = dot(plane.getNormal(), ray.getDirection());
// If we get here, we already know that the rays origin is not included
// in the plane. Thus if we have a zero denominator we have
// a ray paralell to the plane. That is no intersection.
if (fabs(den) <= SGLimits<T>::min())
return false;
// We would now compute \alpha = num/den and compare with 0 and 1.
// But to avoid that expensive division, check equation multiplied by
// the denominator.
T alpha = num/den;
if (alpha < 0)
return false;
dst = ray.getOrigin() + alpha*ray.getDirection();
return true;
}
// make it symmetric
template<typename T>
inline bool
intersects(SGVec3<T>& dst, const SGPlane<T>& plane, const SGRay<T>& ray)
{ return intersects(dst, ray, plane); }
template<typename T>
inline bool
intersects(const SGLineSegment<T>& lineSegment, const SGPlane<T>& plane)
{
// We compute the intersection point
// x = origin + \alpha*direction
// from the line segments origin and non nomalized direction.
// For 0 <= \alpha <= 1 the line segment intersects the infinite plane.
// The intersection point x can also be written
// x = n*dist + y
// where n is the planes normal, dist is the distance of the plane from
// the origin in normal direction and y is ana aproriate vector
// perpendicular to n.
// Equate the x values and take the scalar product with the plane normal n.
// dot(n, origin) + \alpha*dot(n, direction) = dist
// We can now compute alpha from the above equation.
// \alpha = (dist - dot(n, origin))/dot(n, direction)
// The negative numerator for the \alpha expression
T num = plane.getPositiveDist();
num -= dot(plane.getNormal(), lineSegment.getOrigin());
// If the numerator is zero, we have the lines origin included in the plane
if (fabs(num) <= SGLimits<T>::min())
return true;
// The denominator for the \alpha expression
T den = dot(plane.getNormal(), lineSegment.getDirection());
// If we get here, we already know that the lines origin is not included
// in the plane. Thus if we have a zero denominator we have
// a line paralell to the plane. That is no intersection.
if (fabs(den) <= SGLimits<T>::min())
return false;
// We would now compute \alpha = num/den and compare with 0 and 1.
// But to avoid that expensive division, compare equations
// multiplied by |den|. Note that copysign is usually a compiler intrinsic
// that expands in assembler code that not even stalls the cpus pipes.
T alphaDen = copysign(1, den)*num;
if (alphaDen < 0)
return false;
if (den < alphaDen)
return false;
return true;
}
// make it symmetric
template<typename T>
inline bool
intersects(const SGPlane<T>& plane, const SGLineSegment<T>& lineSegment)
{ return intersects(lineSegment, plane); }
template<typename T>
inline bool
intersects(SGVec3<T>& dst, const SGLineSegment<T>& lineSegment, const SGPlane<T>& plane)
{
// We compute the intersection point
// x = origin + \alpha*direction
// from the line segments origin and non nomalized direction.
// For 0 <= \alpha <= 1 the line segment intersects the infinite plane.
// The intersection point x can also be written
// x = n*dist + y
// where n is the planes normal, dist is the distance of the plane from
// the origin in normal direction and y is an aproriate vector
// perpendicular to n.
// Equate the x values and take the scalar product with the plane normal n.
// dot(n, origin) + \alpha*dot(n, direction) = dist
// We can now compute alpha from the above equation.
// \alpha = (dist - dot(n, origin))/dot(n, direction)
// The negative numerator for the \alpha expression
T num = plane.getPositiveDist();
num -= dot(plane.getNormal(), lineSegment.getOrigin());
// If the numerator is zero, we have the lines origin included in the plane
if (fabs(num) <= SGLimits<T>::min()) {
dst = lineSegment.getOrigin();
return true;
}
// The denominator for the \alpha expression
T den = dot(plane.getNormal(), lineSegment.getDirection());
// If we get here, we already know that the lines origin is not included
// in the plane. Thus if we have a zero denominator we have
// a line paralell to the plane. That is: no intersection.
if (fabs(den) <= SGLimits<T>::min())
return false;
// We would now compute \alpha = num/den and compare with 0 and 1.
// But to avoid that expensive division, check equation multiplied by
// the denominator. FIXME: shall we do so? or compute like that?
T alpha = num/den;
if (alpha < 0)
return false;
if (1 < alpha)
return false;
dst = lineSegment.getOrigin() + alpha*lineSegment.getDirection();
return true;
}
// make it symmetric
template<typename T>
inline bool
intersects(SGVec3<T>& dst, const SGPlane<T>& plane, const SGLineSegment<T>& lineSegment)
{ return intersects(dst, lineSegment, plane); }
// Distance of a line segment to a point
template<typename T>
inline T
distSqr(const SGLineSegment<T>& lineSeg, const SGVec3<T>& p)
{
SGVec3<T> ps = p - lineSeg.getStart();
T psdotdir = dot(ps, lineSeg.getDirection());
if (psdotdir <= 0)
return dot(ps, ps);
SGVec3<T> pe = p - lineSeg.getEnd();
if (0 <= dot(pe, lineSeg.getDirection()))
return dot(pe, pe);
return dot(ps, ps) - psdotdir*psdotdir/dot(lineSeg.getDirection(), lineSeg.getDirection());
}
// make it symmetric
template<typename T>
inline T
distSqr(const SGVec3<T>& p, const SGLineSegment<T>& lineSeg)
{ return distSqr(lineSeg, p); }
// with sqrt
template<typename T>
inline T
dist(const SGVec3<T>& p, const SGLineSegment<T>& lineSeg)
{ return sqrt(distSqr(lineSeg, p)); }
template<typename T>
inline T
dist(const SGLineSegment<T>& lineSeg, const SGVec3<T>& p)
{ return sqrt(distSqr(lineSeg, p)); }
template<typename T>
inline bool
intersects(const SGRay<T>& ray, const SGSphere<T>& sphere)
{
// See Tomas Akeniene - Moeller/Eric Haines: Real Time Rendering,
// second edition, page 571
SGVec3<T> l = sphere.getCenter() - ray.getOrigin();
T s = dot(l, ray.getDirection());
T l2 = dot(l, l);
T r2 = sphere.getRadius2();
if (s < 0 && l2 > r2)
return false;
T d2 = dot(ray.getDirection(), ray.getDirection());
// The original test would read
// T m2 = l2 - s*s/d2;
// if (m2 > r2)
// return false;
// but to avoid the expensive division, we multiply by d2
T m2 = d2*l2 - s*s;
if (m2 > d2*r2)
return false;
return true;
}
// make it symmetric
template<typename T>
inline bool
intersects(const SGSphere<T>& sphere, const SGRay<T>& ray)
{ return intersects(ray, sphere); }
template<typename T>
inline bool
intersects(const SGLineSegment<T>& lineSegment, const SGSphere<T>& sphere)
{
// See Tomas Akeniene - Moeller/Eric Haines: Real Time Rendering,
// second edition, page 571
SGVec3<T> l = sphere.getCenter() - lineSegment.getStart();
T ld = length(lineSegment.getDirection());
T s = dot(l, lineSegment.getDirection())/ld;
T l2 = dot(l, l);
T r2 = sphere.getRadius2();
if (s < 0 && l2 > r2)
return false;
T m2 = l2 - s*s;
if (m2 > r2)
return false;
T q = sqrt(r2 - m2);
T t = s - q;
if (ld < t)
return false;
return true;
}
// make it symmetric
template<typename T>
inline bool
intersects(const SGSphere<T>& sphere, const SGLineSegment<T>& lineSegment)
{ return intersects(lineSegment, sphere); }
template<typename T>
inline bool
// FIXME do not use that default argument later. Just for development now
intersects(SGVec3<T>& x, const SGTriangle<T>& tri, const SGRay<T>& ray, T eps = 0)
{
// See Tomas Akeniene - Moeller/Eric Haines: Real Time Rendering
// Method based on the observation that we are looking for a
// point x that can be expressed in terms of the triangle points
// x = v_0 + u*(v_1 - v_0) + v*(v_2 - v_0)
// with 0 <= u, v and u + v <= 1.
// OTOH it could be expressed in terms of the ray
// x = o + t*d
// Now we can compute u, v and t.
SGVec3<T> p = cross(ray.getDirection(), tri.getEdge(1));
T denom = dot(p, tri.getEdge(0));
T signDenom = copysign(1, denom);
SGVec3<T> s = ray.getOrigin() - tri.getBaseVertex();
SGVec3<T> q = cross(s, tri.getEdge(0));
// Now t would read
// t = 1/denom*dot(q, tri.getEdge(1));
// To avoid an expensive division we multiply by |denom|
T tDenom = signDenom*dot(q, tri.getEdge(1));
if (tDenom < 0)
return false;
// For line segment we would test against
// if (1 < t)
// return false;
// with the original t. The multiplied test would read
// if (absDenom < tDenom)
// return false;
T absDenom = fabs(denom);
T absDenomEps = absDenom*eps;
// T u = 1/denom*dot(p, s);
T u = signDenom*dot(p, s);
if (u < -absDenomEps)
return false;
// T v = 1/denom*dot(q, d);
// if (v < -eps)
// return false;
T v = signDenom*dot(q, ray.getDirection());
if (v < -absDenomEps)
return false;
if (u + v > absDenom + absDenomEps)
return false;
// return if paralell ??? FIXME what if paralell and in plane?
// may be we are ok below than anyway??
if (absDenom <= SGLimits<T>::min())
return false;
x = ray.getOrigin();
// if we have survived here it could only happen with denom == 0
// that the point is already in plane. Then return the origin ...
if (SGLimitsd::min() < absDenom)
x += (tDenom/absDenom)*ray.getDirection();
return true;
}
template<typename T>
inline bool
intersects(const SGTriangle<T>& tri, const SGRay<T>& ray, T eps = 0)
{
// 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, ray, eps);
}
template<typename T>
inline bool
// FIXME do not use that default argument later. Just for development now
intersects(SGVec3<T>& x, const SGTriangle<T>& tri, const SGLineSegment<T>& lineSegment, T eps = 0)
{
// See Tomas Akeniene - Moeller/Eric Haines: Real Time Rendering
// Method based on the observation that we are looking for a
// point x that can be expressed in terms of the triangle points
// x = v_0 + u*(v_1 - v_0) + v*(v_2 - v_0)
// with 0 <= u, v and u + v <= 1.
// OTOH it could be expressed in terms of the lineSegment
// x = o + t*d
// Now we can compute u, v and t.
SGVec3<T> p = cross(lineSegment.getDirection(), tri.getEdge(1));
T denom = dot(p, tri.getEdge(0));
T signDenom = copysign(1, denom);
SGVec3<T> s = lineSegment.getStart() - tri.getBaseVertex();
SGVec3<T> q = cross(s, tri.getEdge(0));
// Now t would read
// t = 1/denom*dot(q, tri.getEdge(1));
// To avoid an expensive division we multiply by |denom|
T tDenom = signDenom*dot(q, tri.getEdge(1));
if (tDenom < 0)
return false;
// For line segment we would test against
// if (1 < t)
// return false;
// with the original t. The multiplied test reads
T absDenom = fabs(denom);
if (absDenom < tDenom)
return false;
// take the CPU accuracy in account
T absDenomEps = absDenom*eps;
// T u = 1/denom*dot(p, s);
T u = signDenom*dot(p, s);
if (u < -absDenomEps)
return false;
// T v = 1/denom*dot(q, d);
// if (v < -eps)
// return false;
T v = signDenom*dot(q, lineSegment.getDirection());
if (v < -absDenomEps)
return false;
if (u + v > absDenom + absDenomEps)
return false;
// return if paralell ??? FIXME what if paralell and in plane?
// may be we are ok below than anyway??
if (absDenom <= SGLimits<T>::min())
return false;
x = lineSegment.getStart();
// if we have survived here it could only happen with denom == 0
// that the point is already in plane. Then return the origin ...
if (SGLimitsd::min() < absDenom)
x += (tDenom/absDenom)*lineSegment.getDirection();
return true;
}
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
// well optimized, implement that special case
SGVec3<T> dummy;
return intersects(dummy, tri, lineSegment, eps);
}
template<typename T>
inline bool
intersects(const SGVec3<T>& v, const SGSphere<T>& sphere)
{
if (sphere.empty())
return false;
return distSqr(v, sphere.getCenter()) <= sphere.getRadius2();
}
template<typename T>
inline bool
intersects(const SGSphere<T>& sphere, const SGVec3<T>& v)
{ return intersects(v, sphere); }
template<typename T>
inline bool
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> v(fabs(w.x()), fabs(w.y()), fabs(w.z()));
SGVec3<T> h = 0.5*box.getSize();
if (fabs(c[0]) > v[0] + h[0])
return false;
if (fabs(c[1]) > v[1] + h[1])
return false;
if (fabs(c[2]) > v[2] + h[2])
return false;
if (fabs(c[1]*w[2] - c[2]*w[1]) > h[1]*v[2] + h[2]*v[1])
return false;
if (fabs(c[0]*w[2] - c[2]*w[0]) > h[0]*v[2] + h[2]*v[0])
return false;
if (fabs(c[0]*w[1] - c[1]*w[0]) > h[0]*v[1] + h[1]*v[0])
return false;
return true;
}
template<typename T>
inline bool
intersects(const SGLineSegment<T>& lineSegment, const SGBox<T>& box)
{ return intersects(box, lineSegment); }
template<typename T>
inline bool
intersects(const SGBox<T>& box, const SGRay<T>& ray)
{
// See Tomas Akeniene - Moeller/Eric Haines: Real Time Rendering
for (unsigned i = 0; i < 3; ++i) {
T cMin = box.getMin()[i];
T cMax = box.getMax()[i];
T cOrigin = ray.getOrigin()[i];
T cDir = ray.getDirection()[i];
if (fabs(cDir) <= SGLimits<T>::min()) {
if (cOrigin < cMin)
return false;
if (cMax < cOrigin)
return false;
}
T nearr = - SGLimits<T>::max();
T farr = SGLimits<T>::max();
T T1 = (cMin - cOrigin) / cDir;
T T2 = (cMax - cOrigin) / cDir;
if (T1 > T2) std::swap (T1, T2);/* since T1 intersection with near plane */
if (T1 > nearr) nearr = T1; /* want largest Tnear */
if (T2 < farr) farr = T2; /* want smallest Tfarr */
if (nearr > farr) // farr box is missed
return false;
if (farr < 0) // box is behind ray
return false;
}
return true;
}
// make it symmetric
template<typename T>
inline bool
intersects(const SGRay<T>& ray, const SGBox<T>& box)
{ return intersects(box, ray); }
#endif

29
simgear/math/SGLimits.hxx Normal file
View File

@@ -0,0 +1,29 @@
// Copyright (C) 2006 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 SGLimits_H
#define SGLimits_H
#include <limits>
/// Helper class for epsilon and so on
/// This is the possible place to hook in for machines not
/// providing numeric_limits ...
template<typename T>
class SGLimits : public std::numeric_limits<T> {};
#endif

View File

@@ -0,0 +1,62 @@
// Copyright (C) 2006 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 SGLineSegment_H
#define SGLineSegment_H
template<typename T>
class SGLineSegment {
public:
SGLineSegment()
{ }
SGLineSegment(const SGVec3<T>& start, const SGVec3<T>& end) :
_start(start),
_direction(end - start)
{ }
void set(const SGVec3<T>& start, const SGVec3<T>& end)
{ _start = start; _direction = end - start; }
const SGVec3<T>& getStart() const
{ return _start; }
SGVec3<T> getEnd() const
{ return _start + _direction; }
const SGVec3<T>& getDirection() const
{ return _direction; }
SGVec3<T> getNormalizedDirection() const
{ return normalize(getDirection()); }
SGVec3<T> getCenter() const
{ return _start + T(0.5)*_direction; }
private:
SGVec3<T> _start;
SGVec3<T> _direction;
};
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s,
const SGLineSegment<T>& lineSegment)
{
return s << "line segment: start = " << lineSegment.getStart()
<< ", end = " << lineSegment.getEnd();
}
#endif

44
simgear/math/SGMath.hxx Normal file
View File

@@ -0,0 +1,44 @@
// Copyright (C) 2006 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 SGMath_H
#define SGMath_H
/// Just include them all
#include <iosfwd>
// FIXME, make it compile on IRIX
#include <osg/GL>
#undef GLUT_APIENTRY_DEFINED // GL/glut.h undef APIENTRY when this symbol is defined. osg/GL defines it (?).
// This probably would work if we didn't use plib/pu.h that include GL/glut.h
// on its side.
#include "SGMathFwd.hxx"
#include "SGCMath.hxx"
#include "SGLimits.hxx"
#include "SGMisc.hxx"
#include "SGGeodesy.hxx"
#include "SGVec2.hxx"
#include "SGVec3.hxx"
#include "SGVec4.hxx"
#include "SGGeoc.hxx"
#include "SGGeod.hxx"
#include "SGQuat.hxx"
#include "SGMatrix.hxx"
#endif

View File

@@ -0,0 +1,56 @@
// Copyright (C) 2006 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 SGMathFwd_H
#define SGMathFwd_H
// All forward declarations in case they only need to be declared
class SGGeoc;
class SGGeod;
template<typename T>
class SGLimits;
template<typename T>
class SGMatrix;
template<typename T>
class SGMisc;
template<typename T>
class SGQuat;
template<typename T>
class SGVec2;
template<typename T>
class SGVec3;
template<typename T>
class SGVec4;
typedef SGLimits<float> SGLimitsf;
typedef SGLimits<double> SGLimitsd;
typedef SGMatrix<float> SGMatrixf;
typedef SGMatrix<double> SGMatrixd;
typedef SGMisc<float> SGMiscf;
typedef SGMisc<double> SGMiscd;
typedef SGQuat<float> SGQuatf;
typedef SGQuat<double> SGQuatd;
typedef SGVec2<float> SGVec2f;
typedef SGVec2<double> SGVec2d;
typedef SGVec3<float> SGVec3f;
typedef SGVec3<double> SGVec3d;
typedef SGVec4<float> SGVec4f;
typedef SGVec4<double> SGVec4d;
#endif

366
simgear/math/SGMathTest.cxx Normal file
View File

@@ -0,0 +1,366 @@
// Copyright (C) 2006 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 <cstdlib>
#include <iostream>
#include <plib/sg.h>
#include "SGMath.hxx"
template<typename T>
bool
Vec3Test(void)
{
SGVec3<T> v1, v2, v3;
// Check if the equivalent function works
v1 = SGVec3<T>(1, 2, 3);
v2 = SGVec3<T>(3, 2, 1);
if (equivalent(v1, v2))
return false;
// Check the unary minus operator
v3 = SGVec3<T>(-1, -2, -3);
if (!equivalent(-v1, v3))
return false;
// Check the unary plus operator
v3 = SGVec3<T>(1, 2, 3);
if (!equivalent(+v1, v3))
return false;
// Check the addition operator
v3 = SGVec3<T>(4, 4, 4);
if (!equivalent(v1 + v2, v3))
return false;
// Check the subtraction operator
v3 = SGVec3<T>(-2, 0, 2);
if (!equivalent(v1 - v2, v3))
return false;
// Check the scaler multiplication operator
v3 = SGVec3<T>(2, 4, 6);
if (!equivalent(2*v1, v3))
return false;
// Check the dot product
if (fabs(dot(v1, v2) - 10) > 10*SGLimits<T>::epsilon())
return false;
// Check the cross product
v3 = SGVec3<T>(-4, 8, -4);
if (!equivalent(cross(v1, v2), v3))
return false;
// Check the euclidean length
if (fabs(14 - length(v1)*length(v1)) > 14*SGLimits<T>::epsilon())
return false;
return true;
}
template<typename T>
bool
QuatTest(void)
{
const SGVec3<T> e1(1, 0, 0);
const SGVec3<T> e2(0, 1, 0);
const SGVec3<T> e3(0, 0, 1);
SGVec3<T> v1, v2;
SGQuat<T> q1, q2, q3, q4;
// Check a rotation around the x axis
q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e1);
v1 = SGVec3<T>(1, 2, 3);
v2 = SGVec3<T>(1, -2, -3);
if (!equivalent(q1.transform(v1), v2))
return false;
// Check a rotation around the x axis
q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e1);
v2 = SGVec3<T>(1, 3, -2);
if (!equivalent(q1.transform(v1), v2))
return false;
// Check a rotation around the y axis
q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e2);
v2 = SGVec3<T>(-1, 2, -3);
if (!equivalent(q1.transform(v1), v2))
return false;
// Check a rotation around the y axis
q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e2);
v2 = SGVec3<T>(-3, 2, 1);
if (!equivalent(q1.transform(v1), v2))
return false;
// Check a rotation around the z axis
q1 = SGQuat<T>::fromAngleAxis(SGMisc<T>::pi(), e3);
v2 = SGVec3<T>(-1, -2, 3);
if (!equivalent(q1.transform(v1), v2))
return false;
// Check a rotation around the z axis
q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e3);
v2 = SGVec3<T>(2, -1, 3);
if (!equivalent(q1.transform(v1), v2))
return false;
// Now check some successive transforms
// We can reuse the prevously tested stuff
q1 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e1);
q2 = SGQuat<T>::fromAngleAxis(0.5*SGMisc<T>::pi(), e2);
q3 = q1*q2;
v2 = q2.transform(q1.transform(v1));
if (!equivalent(q3.transform(v1), v2))
return false;
/// Test from Euler angles
float x = 0.2*SGMisc<T>::pi();
float y = 0.3*SGMisc<T>::pi();
float z = 0.4*SGMisc<T>::pi();
q1 = SGQuat<T>::fromAngleAxis(z, e3);
q2 = SGQuat<T>::fromAngleAxis(y, e2);
q3 = SGQuat<T>::fromAngleAxis(x, e1);
v2 = q3.transform(q2.transform(q1.transform(v1)));
q4 = SGQuat<T>::fromEulerRad(z, y, x);
if (!equivalent(q4.transform(v1), v2))
return false;
/// Test angle axis forward and back transform
q1 = SGQuat<T>::fromAngleAxis(0.2*SGMisc<T>::pi(), e1);
q2 = SGQuat<T>::fromAngleAxis(0.7*SGMisc<T>::pi(), e2);
q3 = q1*q2;
SGVec3<T> angleAxis;
q1.getAngleAxis(angleAxis);
q4 = SGQuat<T>::fromAngleAxis(angleAxis);
if (!equivalent(q1, q4))
return false;
q2.getAngleAxis(angleAxis);
q4 = SGQuat<T>::fromAngleAxis(angleAxis);
if (!equivalent(q2, q4))
return false;
q3.getAngleAxis(angleAxis);
q4 = SGQuat<T>::fromAngleAxis(angleAxis);
if (!equivalent(q3, q4))
return false;
return true;
}
template<typename T>
bool
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;
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);
if (!equivalent(m1, m2))
return false;
// Check matrix multiplication and inversion
if (!equivalent(m0*m1, SGMatrix<T>::unit()))
return false;
if (!equivalent(m1*m0, SGMatrix<T>::unit()))
return false;
if (!equivalent(m0*m2, SGMatrix<T>::unit()))
return false;
if (!equivalent(m2*m0, SGMatrix<T>::unit()))
return false;
return true;
}
bool
GeodesyTest(void)
{
// We know that the values are on the order of 1
double epsDeg = 10*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();
SGVec3<double> cart0, cart1;
SGGeod geod0, geod1;
SGGeoc geoc0;
// create some geodetic position
geod0 = SGGeod::fromDegM(30, 20, 17);
// Test the conversion routines to cartesian coordinates
cart0 = SGVec3<double>::fromGeod(geod0);
geod1 = SGGeod::fromCart(cart0);
if (epsDeg < fabs(geod0.getLongitudeDeg() - geod1.getLongitudeDeg()) ||
epsDeg < fabs(geod0.getLatitudeDeg() - geod1.getLatitudeDeg()) ||
epsM < fabs(geod0.getElevationM() - geod1.getElevationM()))
return false;
// Test the conversion routines to radial coordinates
geoc0 = SGGeoc::fromCart(cart0);
cart1 = SGVec3<double>::fromGeoc(geoc0);
if (!equivalent(cart0, cart1))
return false;
return true;
}
bool
sgInterfaceTest(void)
{
SGVec3f v3f = SGVec3f::e2();
SGVec4f v4f = SGVec4f::e2();
SGQuatf qf = SGQuatf::fromEulerRad(1.2, 1.3, -0.4);
SGMatrixf mf;
mf.postMultTranslate(v3f);
mf.postMultRotate(qf);
// Copy to and from plibs types check if result is equal,
// test for exact equality
SGVec3f tv3f;
sgVec3 sv3f;
sgCopyVec3(sv3f, v3f.sg());
sgCopyVec3(tv3f.sg(), sv3f);
if (tv3f != v3f)
return false;
// Copy to and from plibs types check if result is equal,
// test for exact equality
SGVec4f tv4f;
sgVec4 sv4f;
sgCopyVec4(sv4f, v4f.sg());
sgCopyVec4(tv4f.sg(), sv4f);
if (tv4f != v4f)
return false;
// Copy to and from plibs types check if result is equal,
// test for exact equality
SGQuatf tqf;
sgQuat sqf;
sgCopyQuat(sqf, qf.sg());
sgCopyQuat(tqf.sg(), sqf);
if (tqf != qf)
return false;
// Copy to and from plibs types check if result is equal,
// test for exact equality
SGMatrixf tmf;
sgMat4 smf;
sgCopyMat4(smf, mf.sg());
sgCopyMat4(tmf.sg(), smf);
if (tmf != mf)
return false;
return true;
}
bool
sgdInterfaceTest(void)
{
SGVec3d v3d = SGVec3d::e2();
SGVec4d v4d = SGVec4d::e2();
SGQuatd qd = SGQuatd::fromEulerRad(1.2, 1.3, -0.4);
SGMatrixd md;
md.postMultTranslate(v3d);
md.postMultRotate(qd);
// Copy to and from plibs types check if result is equal,
// test for exact equality
SGVec3d tv3d;
sgdVec3 sv3d;
sgdCopyVec3(sv3d, v3d.sg());
sgdCopyVec3(tv3d.sg(), sv3d);
if (tv3d != v3d)
return false;
// Copy to and from plibs types check if result is equal,
// test for exact equality
SGVec4d tv4d;
sgdVec4 sv4d;
sgdCopyVec4(sv4d, v4d.sg());
sgdCopyVec4(tv4d.sg(), sv4d);
if (tv4d != v4d)
return false;
// Copy to and from plibs types check if result is equal,
// test for exact equality
SGQuatd tqd;
sgdQuat sqd;
sgdCopyQuat(sqd, qd.sg());
sgdCopyQuat(tqd.sg(), sqd);
if (tqd != qd)
return false;
// Copy to and from plibs types check if result is equal,
// test for exact equality
SGMatrixd tmd;
sgdMat4 smd;
sgdCopyMat4(smd, md.sg());
sgdCopyMat4(tmd.sg(), smd);
if (tmd != md)
return false;
return true;
}
int
main(void)
{
// Do vector tests
if (!Vec3Test<float>())
return EXIT_FAILURE;
if (!Vec3Test<double>())
return EXIT_FAILURE;
// Do quaternion tests
if (!QuatTest<float>())
return EXIT_FAILURE;
if (!QuatTest<double>())
return EXIT_FAILURE;
// Do matrix tests
if (!MatrixTest<float>())
return EXIT_FAILURE;
if (!MatrixTest<double>())
return EXIT_FAILURE;
// Check geodetic/geocentric/cartesian conversions
if (!GeodesyTest())
return EXIT_FAILURE;
// Check interaction with sg*/sgd*
if (!sgInterfaceTest())
return EXIT_FAILURE;
if (!sgdInterfaceTest())
return EXIT_FAILURE;
std::cout << "Successfully passed all tests!" << std::endl;
return EXIT_SUCCESS;
}

612
simgear/math/SGMatrix.hxx Normal file
View File

@@ -0,0 +1,612 @@
// Copyright (C) 2006 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 SGMatrix_H
#define SGMatrix_H
/// Expression templates for poor programmers ... :)
template<typename T>
struct TransNegRef;
/// 3D Matrix Class
template<typename T>
class SGMatrix {
public:
enum { nCols = 4, nRows = 4, nEnts = 16 };
typedef T value_type;
/// Default constructor. Does not initialize at all.
/// If you need them zero initialized, use SGMatrix::zeros()
SGMatrix(void)
{
/// Initialize with nans in the debug build, that will guarantee to have
/// a fast uninitialized default constructor in the release but shows up
/// uninitialized values in the debug build very fast ...
#ifndef NDEBUG
for (unsigned i = 0; i < nEnts; ++i)
_data.flat[i] = SGLimits<T>::quiet_NaN();
#endif
}
/// Constructor. Initialize by the content of a plain array,
/// make sure it has at least 16 elements
explicit SGMatrix(const T* data)
{ for (unsigned i = 0; i < nEnts; ++i) _data.flat[i] = data[i]; }
/// Constructor, build up a SGMatrix from given elements
SGMatrix(T m00, T m01, T m02, T m03,
T m10, T m11, T m12, T m13,
T m20, T m21, T m22, T m23,
T m30, T m31, T m32, T m33)
{
_data.flat[0] = m00; _data.flat[1] = m10;
_data.flat[2] = m20; _data.flat[3] = m30;
_data.flat[4] = m01; _data.flat[5] = m11;
_data.flat[6] = m21; _data.flat[7] = m31;
_data.flat[8] = m02; _data.flat[9] = m12;
_data.flat[10] = m22; _data.flat[11] = m32;
_data.flat[12] = m03; _data.flat[13] = m13;
_data.flat[14] = m23; _data.flat[15] = m33;
}
/// Constructor, build up a SGMatrix from a translation
template<typename S>
SGMatrix(const SGVec3<S>& trans)
{ set(trans); }
/// Constructor, build up a SGMatrix from a rotation and a translation
template<typename S>
SGMatrix(const SGQuat<S>& quat)
{ set(quat); }
/// Copy constructor for a transposed negated matrix
SGMatrix(const TransNegRef<T>& tm)
{ set(tm); }
/// Set from a tranlation
template<typename S>
void set(const SGVec3<S>& trans)
{
_data.flat[0] = 1; _data.flat[4] = 0;
_data.flat[8] = 0; _data.flat[12] = T(trans(0));
_data.flat[1] = 0; _data.flat[5] = 1;
_data.flat[9] = 0; _data.flat[13] = T(trans(1));
_data.flat[2] = 0; _data.flat[6] = 0;
_data.flat[10] = 1; _data.flat[14] = T(trans(2));
_data.flat[3] = 0; _data.flat[7] = 0;
_data.flat[11] = 0; _data.flat[15] = 1;
}
/// Set from a scale/rotation and tranlation
template<typename S>
void set(const SGQuat<S>& quat)
{
T w = quat.w(); T x = quat.x(); T y = quat.y(); T z = quat.z();
T xx = x*x; T yy = y*y; T zz = z*z;
T wx = w*x; T wy = w*y; T wz = w*z;
T xy = x*y; T xz = x*z; T yz = y*z;
_data.flat[0] = 1-2*(yy+zz); _data.flat[1] = 2*(xy-wz);
_data.flat[2] = 2*(xz+wy); _data.flat[3] = 0;
_data.flat[4] = 2*(xy+wz); _data.flat[5] = 1-2*(xx+zz);
_data.flat[6] = 2*(yz-wx); _data.flat[7] = 0;
_data.flat[8] = 2*(xz-wy); _data.flat[9] = 2*(yz+wx);
_data.flat[10] = 1-2*(xx+yy); _data.flat[11] = 0;
_data.flat[12] = 0; _data.flat[13] = 0;
_data.flat[14] = 0; _data.flat[15] = 1;
}
/// set from a transposed negated matrix
void set(const TransNegRef<T>& tm)
{
const SGMatrix& m = tm.m;
_data.flat[0] = m(0,0);
_data.flat[1] = m(0,1);
_data.flat[2] = m(0,2);
_data.flat[3] = m(3,0);
_data.flat[4] = m(1,0);
_data.flat[5] = m(1,1);
_data.flat[6] = m(1,2);
_data.flat[7] = m(3,1);
_data.flat[8] = m(2,0);
_data.flat[9] = m(2,1);
_data.flat[10] = m(2,2);
_data.flat[11] = m(3,2);
// Well, this one is ugly here, as that xform method on the current
// object needs the above data to be already set ...
SGVec3<T> t = xformVec(SGVec3<T>(m(0,3), m(1,3), m(2,3)));
_data.flat[12] = -t(0);
_data.flat[13] = -t(1);
_data.flat[14] = -t(2);
_data.flat[15] = m(3,3);
}
/// Access by index, the index is unchecked
const T& operator()(unsigned i, unsigned j) const
{ return _data.flat[i + 4*j]; }
/// Access by index, the index is unchecked
T& operator()(unsigned i, unsigned j)
{ return _data.flat[i + 4*j]; }
/// Access raw data by index, the index is unchecked
const T& operator[](unsigned i) const
{ return _data.flat[i]; }
/// Access by index, the index is unchecked
T& operator[](unsigned i)
{ return _data.flat[i]; }
/// Get the data pointer
const T* data(void) const
{ return _data.flat; }
/// Get the data pointer
T* data(void)
{ return _data.flat; }
/// Readonly interface function to ssg's sgMat4/sgdMat4
const T (&sg(void) const)[4][4]
{ return _data.carray; }
/// Interface function to ssg's sgMat4/sgdMat4
T (&sg(void))[4][4]
{ return _data.carray; }
/// Inplace addition
SGMatrix& operator+=(const SGMatrix& m)
{ for (unsigned i = 0; i < nEnts; ++i) _data.flat[i] += m._data.flat[i]; return *this; }
/// Inplace subtraction
SGMatrix& operator-=(const SGMatrix& m)
{ for (unsigned i = 0; i < nEnts; ++i) _data.flat[i] -= m._data.flat[i]; return *this; }
/// Inplace scalar multiplication
template<typename S>
SGMatrix& operator*=(S s)
{ for (unsigned i = 0; i < nEnts; ++i) _data.flat[i] *= s; return *this; }
/// Inplace scalar multiplication by 1/s
template<typename S>
SGMatrix& operator/=(S s)
{ return operator*=(1/T(s)); }
/// Inplace matrix multiplication, post multiply
SGMatrix& operator*=(const SGMatrix<T>& m2);
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));
return *this;
}
template<typename S>
SGMatrix& postMultTranslate(const SGVec3<S>& t)
{
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));
col3 += T(t(i))*tmp;
}
(*this)(0,3) = col3(0); (*this)(1,3) = col3(1);
(*this)(2,3) = col3(2); (*this)(3,3) = col3(3);
return *this;
}
SGMatrix& preMultRotate(const SGQuat<T>& r)
{
for (unsigned i = 0; i < SGMatrix<T>::nCols; ++i) {
SGVec3<T> col((*this)(0,i), (*this)(1,i), (*this)(2,i));
col = r.transform(col);
(*this)(0,i) = col(0); (*this)(1,i) = col(1); (*this)(2,i) = col(2);
}
return *this;
}
SGMatrix& postMultRotate(const SGQuat<T>& r)
{
for (unsigned i = 0; i < SGMatrix<T>::nCols; ++i) {
SGVec3<T> col((*this)(i,0), (*this)(i,1), (*this)(i,2));
col = r.backTransform(col);
(*this)(i,0) = col(0); (*this)(i,1) = col(1); (*this)(i,2) = col(2);
}
return *this;
}
SGVec3<T> xformPt(const SGVec3<T>& pt) const
{
SGVec3<T> tpt;
tpt(0) = (*this)(0,3);
tpt(1) = (*this)(1,3);
tpt(2) = (*this)(2,3);
for (unsigned i = 0; i < SGMatrix<T>::nCols-1; ++i) {
T tmp = pt(i);
tpt(0) += tmp*(*this)(0,i);
tpt(1) += tmp*(*this)(1,i);
tpt(2) += tmp*(*this)(2,i);
}
return tpt;
}
SGVec3<T> xformVec(const SGVec3<T>& v) const
{
SGVec3<T> tv;
T tmp = v(0);
tv(0) = tmp*(*this)(0,0);
tv(1) = tmp*(*this)(1,0);
tv(2) = tmp*(*this)(2,0);
for (unsigned i = 1; i < SGMatrix<T>::nCols-1; ++i) {
T tmp = v(i);
tv(0) += tmp*(*this)(0,i);
tv(1) += tmp*(*this)(1,i);
tv(2) += tmp*(*this)(2,i);
}
return tv;
}
/// Return an all zero matrix
static SGMatrix zeros(void)
{ return SGMatrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); }
/// Return a unit matrix
static SGMatrix unit(void)
{ return SGMatrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
private:
/// Required to make that alias safe.
union Data {
T flat[16];
T carray[4][4];
};
/// The actual data, the matrix is stored in column major order,
/// that matches the storage format of OpenGL
Data _data;
};
/// Class to distinguish between a matrix and the matrix with a transposed
/// rotational part and a negated translational part
template<typename T>
struct TransNegRef {
TransNegRef(const SGMatrix<T>& _m) : m(_m) {}
const SGMatrix<T>& m;
};
/// Unary +, do nothing ...
template<typename T>
inline
const SGMatrix<T>&
operator+(const SGMatrix<T>& m)
{ return m; }
/// Unary -, do nearly nothing
template<typename T>
inline
SGMatrix<T>
operator-(const SGMatrix<T>& m)
{
SGMatrix<T> ret;
for (unsigned i = 0; i < SGMatrix<T>::nEnts; ++i)
ret[i] = -m[i];
return ret;
}
/// Binary +
template<typename T>
inline
SGMatrix<T>
operator+(const SGMatrix<T>& m1, const SGMatrix<T>& m2)
{
SGMatrix<T> ret;
for (unsigned i = 0; i < SGMatrix<T>::nEnts; ++i)
ret[i] = m1[i] + m2[i];
return ret;
}
/// Binary -
template<typename T>
inline
SGMatrix<T>
operator-(const SGMatrix<T>& m1, const SGMatrix<T>& m2)
{
SGMatrix<T> ret;
for (unsigned i = 0; i < SGMatrix<T>::nEnts; ++i)
ret[i] = m1[i] - m2[i];
return ret;
}
/// Scalar multiplication
template<typename S, typename T>
inline
SGMatrix<T>
operator*(S s, const SGMatrix<T>& m)
{
SGMatrix<T> ret;
for (unsigned i = 0; i < SGMatrix<T>::nEnts; ++i)
ret[i] = s*m[i];
return ret;
}
/// Scalar multiplication
template<typename S, typename T>
inline
SGMatrix<T>
operator*(const SGMatrix<T>& m, S s)
{
SGMatrix<T> ret;
for (unsigned i = 0; i < SGMatrix<T>::nEnts; ++i)
ret[i] = s*m[i];
return ret;
}
/// Vector multiplication
template<typename T>
inline
SGVec4<T>
operator*(const SGMatrix<T>& m, const SGVec4<T>& v)
{
SGVec4<T> mv;
T tmp = v(0);
mv(0) = tmp*m(0,0);
mv(1) = tmp*m(1,0);
mv(2) = tmp*m(2,0);
mv(3) = tmp*m(3,0);
for (unsigned i = 1; i < SGMatrix<T>::nCols; ++i) {
T tmp = v(i);
mv(0) += tmp*m(0,i);
mv(1) += tmp*m(1,i);
mv(2) += tmp*m(2,i);
mv(3) += tmp*m(3,i);
}
return mv;
}
/// Vector multiplication
template<typename T>
inline
SGVec4<T>
operator*(const TransNegRef<T>& tm, const SGVec4<T>& v)
{
const SGMatrix<T>& m = tm.m;
SGVec4<T> mv;
SGVec3<T> v2;
T tmp = v(3);
mv(0) = v2(0) = -tmp*m(0,3);
mv(1) = v2(1) = -tmp*m(1,3);
mv(2) = v2(2) = -tmp*m(2,3);
mv(3) = tmp*m(3,3);
for (unsigned i = 0; i < SGMatrix<T>::nCols - 1; ++i) {
T tmp = v(i) + v2(i);
mv(0) += tmp*m(i,0);
mv(1) += tmp*m(i,1);
mv(2) += tmp*m(i,2);
mv(3) += tmp*m(3,i);
}
return mv;
}
/// Matrix multiplication
template<typename T>
inline
SGMatrix<T>
operator*(const SGMatrix<T>& m1, const SGMatrix<T>& m2)
{
SGMatrix<T> m;
for (unsigned j = 0; j < SGMatrix<T>::nCols; ++j) {
T tmp = m2(0,j);
m(0,j) = tmp*m1(0,0);
m(1,j) = tmp*m1(1,0);
m(2,j) = tmp*m1(2,0);
m(3,j) = tmp*m1(3,0);
for (unsigned i = 1; i < SGMatrix<T>::nCols; ++i) {
T tmp = m2(i,j);
m(0,j) += tmp*m1(0,i);
m(1,j) += tmp*m1(1,i);
m(2,j) += tmp*m1(2,i);
m(3,j) += tmp*m1(3,i);
}
}
return m;
}
/// Inplace matrix multiplication, post multiply
template<typename T>
inline
SGMatrix<T>&
SGMatrix<T>::operator*=(const SGMatrix<T>& m2)
{ (*this) = operator*(*this, m2); return *this; }
/// Return a reference to the matrix typed to make sure we use the transposed
/// negated matrix
template<typename T>
inline
TransNegRef<T>
transNeg(const SGMatrix<T>& m)
{ return TransNegRef<T>(m); }
/// Compute the inverse if the matrix src. Store the result in dst.
/// Return if the matrix is nonsingular. If it is singular dst contains
/// undefined values
template<typename T>
inline
bool
invert(SGMatrix<T>& dst, const SGMatrix<T>& src)
{
// Do a LU decomposition with row pivoting and solve into dst
SGMatrix<T> tmp = src;
dst = SGMatrix<T>::unit();
for (unsigned i = 0; i < 4; ++i) {
T val = tmp(i,i);
unsigned ind = i;
// Find the row with the maximum value in the i-th colum
for (unsigned j = i + 1; j < 4; ++j) {
if (fabs(tmp(j, i)) > fabs(val)) {
ind = j;
val = tmp(j, i);
}
}
// Do row pivoting
if (ind != i) {
for (unsigned j = 0; j < 4; ++j) {
T t;
t = dst(i,j); dst(i,j) = dst(ind,j); dst(ind,j) = t;
t = tmp(i,j); tmp(i,j) = tmp(ind,j); tmp(ind,j) = t;
}
}
// Check for singularity
if (fabs(val) <= SGLimits<T>::min())
return false;
T ival = 1/val;
for (unsigned j = 0; j < 4; ++j) {
tmp(i,j) *= ival;
dst(i,j) *= ival;
}
for (unsigned j = 0; j < 4; ++j) {
if (j == i)
continue;
val = tmp(j,i);
for (unsigned k = 0; k < 4; ++k) {
tmp(j,k) -= tmp(i,k) * val;
dst(j,k) -= dst(i,k) * val;
}
}
}
return true;
}
/// The 1-norm of the matrix, this is the largest column sum of
/// the absolute values of A.
template<typename T>
inline
T
norm1(const SGMatrix<T>& m)
{
T nrm = 0;
for (unsigned i = 0; i < SGMatrix<T>::nRows; ++i) {
T sum = fabs(m(i, 0)) + fabs(m(i, 1)) + fabs(m(i, 2)) + fabs(m(i, 3));
if (nrm < sum)
nrm = sum;
}
return nrm;
}
/// The inf-norm of the matrix, this is the largest row sum of
/// the absolute values of A.
template<typename T>
inline
T
normInf(const SGMatrix<T>& m)
{
T nrm = 0;
for (unsigned i = 0; i < SGMatrix<T>::nCols; ++i) {
T sum = fabs(m(0, i)) + fabs(m(1, i)) + fabs(m(2, i)) + fabs(m(3, i));
if (nrm < sum)
nrm = sum;
}
return nrm;
}
/// Return true if exactly the same
template<typename T>
inline
bool
operator==(const SGMatrix<T>& m1, const SGMatrix<T>& m2)
{
for (unsigned i = 0; i < SGMatrix<T>::nEnts; ++i)
if (m1[i] != m2[i])
return false;
return true;
}
/// Return true if not exactly the same
template<typename T>
inline
bool
operator!=(const SGMatrix<T>& m1, const SGMatrix<T>& m2)
{ return ! (m1 == m2); }
/// Return true if equal to the relative tolerance tol
template<typename T>
inline
bool
equivalent(const SGMatrix<T>& m1, const SGMatrix<T>& m2, T rtol, T atol)
{ return norm1(m1 - m2) < rtol*(norm1(m1) + norm1(m2)) + atol; }
/// Return true if equal to the relative tolerance tol
template<typename T>
inline
bool
equivalent(const SGMatrix<T>& m1, const SGMatrix<T>& m2, T rtol)
{ return norm1(m1 - m2) < rtol*(norm1(m1) + norm1(m2)); }
/// Return true if about equal to roundoff of the underlying type
template<typename T>
inline
bool
equivalent(const SGMatrix<T>& m1, const SGMatrix<T>& m2)
{
T tol = 100*SGLimits<T>::epsilon();
return equivalent(m1, m2, tol, tol);
}
#ifndef NDEBUG
template<typename T>
inline
bool
isNaN(const SGMatrix<T>& m)
{
for (unsigned i = 0; i < SGMatrix<T>::nEnts; ++i) {
if (SGMisc<T>::isNaN(m[i]))
return true;
}
return false;
}
#endif
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGMatrix<T>& m)
{
s << "[ " << m(0,0) << ", " << m(0,1) << ", " << m(0,2) << ", " << m(0,3) << "\n";
s << " " << m(1,0) << ", " << m(1,1) << ", " << m(1,2) << ", " << m(1,3) << "\n";
s << " " << m(2,0) << ", " << m(2,1) << ", " << m(2,2) << ", " << m(2,3) << "\n";
s << " " << m(3,0) << ", " << m(3,1) << ", " << m(3,2) << ", " << m(3,3) << " ]";
return s;
}
inline
SGMatrixf
toMatrixf(const SGMatrixd& m)
{
return SGMatrixf((float)m(0,0), (float)m(0,1), (float)m(0,2), (float)m(0,3),
(float)m(1,0), (float)m(1,1), (float)m(1,2), (float)m(1,3),
(float)m(2,0), (float)m(2,1), (float)m(2,2), (float)m(2,3),
(float)m(3,0), (float)m(3,1), (float)m(3,2), (float)m(3,3));
}
inline
SGMatrixd
toMatrixd(const SGMatrixf& m)
{
return SGMatrixd(m(0,0), m(0,1), m(0,2), m(0,3),
m(1,0), m(1,1), m(1,2), m(1,3),
m(2,0), m(2,1), m(2,2), m(2,3),
m(3,0), m(3,1), m(3,2), m(3,3));
}
#endif

110
simgear/math/SGMisc.hxx Normal file
View File

@@ -0,0 +1,110 @@
// Copyright (C) 2006 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 SGMisc_H
#define SGMisc_H
template<typename T>
class SGMisc {
public:
static T pi() { return T(3.1415926535897932384626433832795029L); }
static T twopi() { return 2*T(3.1415926535897932384626433832795029L); }
static T min(const T& a, const T& b)
{ return a < b ? a : b; }
static T min(const T& a, const T& b, const T& c)
{ return min(min(a, b), c); }
static T min(const T& a, const T& b, const T& c, const T& d)
{ return min(min(min(a, b), c), d); }
static T max(const T& a, const T& b)
{ return a > b ? a : b; }
static T max(const T& a, const T& b, const T& c)
{ return max(max(a, b), c); }
static T max(const T& a, const T& b, const T& c, const T& d)
{ return max(max(max(a, b), c), d); }
// clip the value of a to be in the range between and including _min and _max
static T clip(const T& a, const T& _min, const T& _max)
{ return max(_min, min(_max, a)); }
static int sign(const T& a)
{
if (a < -SGLimits<T>::min())
return -1;
else if (SGLimits<T>::min() < a)
return 1;
else
return 0;
}
static T rad2deg(const T& val)
{ return val*180/pi(); }
static T deg2rad(const T& val)
{ return val*pi()/180; }
// normalize the value to be in a range between [min, max[
static T
normalizePeriodic(const T& min, const T& max, const T& value)
{
T range = max - min;
if (range < SGLimits<T>::min())
return min;
T normalized = value - range*floor((value - min)/range);
// two security checks that can only happen due to roundoff
if (value <= min)
return min;
if (max <= normalized)
return min;
return normalized;
}
// normalize the angle to be in a range between [-pi, pi[
static T
normalizeAngle(const T& angle)
{ return normalizePeriodic(-pi(), pi(), angle); }
// normalize the angle to be in a range between [0, 2pi[
static T
normalizeAngle2(const T& angle)
{ return normalizePeriodic(0, twopi(), angle); }
static T round(const T& v)
{ return floor(v + T(0.5)); }
static int roundToInt(const T& v)
{ return int(round(v)); }
#ifndef NDEBUG
/// Returns true if v is a NaN value
/// Use with care: allways code that you do not need to use that!
static bool isNaN(const T& v)
{
#ifdef HAVE_ISNAN
return isnan(v);
#elif defined HAVE_STD_ISNAN
return std::isnan(v);
#else
// Use that every compare involving a NaN returns false
// But be careful, some usual compiler switches like for example
// -fast-math from gcc might optimize that expression to v != v which
// behaves exactly like the opposite ...
return !(v == v);
#endif
}
#endif
};
#endif

59
simgear/math/SGPlane.hxx Normal file
View File

@@ -0,0 +1,59 @@
// Copyright (C) 2006 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 SGPlane_H
#define SGPlane_H
template<typename T>
class SGPlane {
public:
SGPlane()
{ }
SGPlane(const SGVec3<T>& normal, T dist) :
_normal(normal), _dist(dist)
{ }
SGPlane(const SGVec3<T> vertices[3]) :
_normal(normalize(cross(vertices[1] - vertices[0],
vertices[2] - vertices[0]))),
_dist(-dot(_normal, vertices[0]))
{ }
void setNormal(const SGVec3<T>& normal)
{ _normal = normal; }
const SGVec3<T>& getNormal() const
{ return _normal; }
void setDist(const T& dist)
{ _dist = dist; }
const T& getDist() const
{ return _dist; }
/// That is the distance where we measure positive in direction of the normal
T getPositiveDist() const
{ return -_dist; }
/// That is the distance where we measure positive in the oposite direction
/// of the normal.
const T& getNegativeDist() const
{ return _dist; }
private:
// That ordering is important because of one constructor
SGVec3<T> _normal;
T _dist;
};
#endif

793
simgear/math/SGQuat.hxx Normal file
View File

@@ -0,0 +1,793 @@
// Copyright (C) 2006 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 SGQuat_H
#define SGQuat_H
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
#include <osg/Quat>
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> {
public:
typedef T value_type;
/// Default constructor. Does not initialize at all.
/// If you need them zero initialized, SGQuat::zeros()
SGQuat(void)
{
/// Initialize with nans in the debug build, that will guarantee to have
/// a fast uninitialized default constructor in the release but shows up
/// uninitialized values in the debug build very fast ...
#ifndef NDEBUG
for (unsigned i = 0; i < 4; ++i)
data()[i] = SGLimits<T>::quiet_NaN();
#endif
}
/// Constructor. Initialize by the given values
SGQuat(T _x, T _y, T _z, T _w)
{ x() = _x; y() = _y; z() = _z; w() = _w; }
/// Constructor. Initialize by the content of a plain array,
/// 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)
{ return fromRealImag(1, SGVec3<T>(0, 0, 0)); }
/// Return a quaternion from euler angles
static SGQuat fromEulerRad(T z, T y, T x)
{
SGQuat q;
T zd2 = T(0.5)*z; T yd2 = T(0.5)*y; T xd2 = T(0.5)*x;
T Szd2 = sin(zd2); T Syd2 = sin(yd2); T Sxd2 = sin(xd2);
T Czd2 = cos(zd2); T Cyd2 = cos(yd2); T Cxd2 = cos(xd2);
T Cxd2Czd2 = Cxd2*Czd2; T Cxd2Szd2 = Cxd2*Szd2;
T Sxd2Szd2 = Sxd2*Szd2; T Sxd2Czd2 = Sxd2*Czd2;
q.w() = Cxd2Czd2*Cyd2 + Sxd2Szd2*Syd2;
q.x() = Sxd2Czd2*Cyd2 - Cxd2Szd2*Syd2;
q.y() = Cxd2Czd2*Syd2 + Sxd2Szd2*Cyd2;
q.z() = Cxd2Szd2*Cyd2 - Sxd2Czd2*Syd2;
return q;
}
/// Return a quaternion from euler angles in degrees
static SGQuat fromEulerDeg(T z, T y, T x)
{
return fromEulerRad(SGMisc<T>::deg2rad(z), SGMisc<T>::deg2rad(y),
SGMisc<T>::deg2rad(x));
}
/// Return a quaternion from euler angles
static SGQuat fromYawPitchRoll(T y, T p, T r)
{ return fromEulerRad(y, p, r); }
/// Return a quaternion from euler angles
static SGQuat fromYawPitchRollDeg(T y, T p, T r)
{ return fromEulerDeg(y, p, r); }
/// Return a quaternion from euler angles
static SGQuat fromHeadAttBank(T h, T a, T b)
{ return fromEulerRad(h, a, b); }
/// Return a quaternion from euler angles
static SGQuat fromHeadAttBankDeg(T h, T a, T b)
{ return fromEulerDeg(h, a, b); }
/// Return a quaternion rotation from the earth centered to the
/// simulation usual horizontal local frame from given
/// longitude and latitude.
/// The horizontal local frame used in simulations is the frame with x-axis
/// pointing north, the y-axis pointing eastwards and the z axis
/// pointing downwards.
static SGQuat fromLonLatRad(T lon, T lat)
{
SGQuat q;
T zd2 = T(0.5)*lon;
T yd2 = T(-0.25)*SGMisc<T>::pi() - T(0.5)*lat;
T Szd2 = sin(zd2);
T Syd2 = sin(yd2);
T Czd2 = cos(zd2);
T Cyd2 = cos(yd2);
q.w() = Czd2*Cyd2;
q.x() = -Szd2*Syd2;
q.y() = Czd2*Syd2;
q.z() = Szd2*Cyd2;
return q;
}
/// Like the above provided for convenience
static SGQuat fromLonLatDeg(T lon, T lat)
{ return fromLonLatRad(SGMisc<T>::deg2rad(lon), SGMisc<T>::deg2rad(lat)); }
/// Like the above provided for convenience
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;
return fromRealImag(cos(angle2), T(sin(angle2))*axis);
}
/// Create a quaternion from the angle axis representation
static SGQuat fromAngleAxisDeg(T angle, const SGVec3<T>& axis)
{ return fromAngleAxis(SGMisc<T>::deg2rad(angle), axis); }
/// Create a quaternion from the angle axis representation where the angle
/// is stored in the axis' length
static SGQuat fromAngleAxis(const SGVec3<T>& axis)
{
T nAxis = norm(axis);
if (nAxis <= SGLimits<T>::min())
return SGQuat(1, 0, 0, 0);
T angle2 = 0.5*nAxis;
return fromRealImag(cos(angle2), T(sin(angle2)/nAxis)*axis);
}
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())
return SGQuat::unit();
return SGQuat::fromRotateToNorm((1/nfrom)*from, (1/nto)*to);
}
// FIXME more finegrained error behavour.
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())
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())
return SGQuat::unit();
// The target vector for the first rotation
SGVec3<T> nto1 = SGVec3<T>::zeros();
SGVec3<T> nto2 = SGVec3<T>::zeros();
nto1[i1] = 1;
nto2[i2] = 1;
// The first rotation can be done with the usual routine.
SGQuat q = SGQuat::fromRotateToNorm(nv1, nto1);
// The rotation axis for the second rotation is the
// target for the first one, so the rotation axis is nto1
// We need to get the angle.
// Make nv2 exactly orthogonal to nv1.
nv2 = normalize(nv2 - dv1v2*nv1);
SGVec3<T> tnv2 = q.transform(nv2);
T cosang = dot(nto2, tnv2);
T cos05ang = T(0.5+0.5*cosang);
if (cos05ang <= 0)
cosang = T(0);
cos05ang = sqrt(cos05ang);
T sig = dot(nto1, cross(nto2, tnv2));
T sin05ang = T(0.5-0.5*cosang);
if (sin05ang <= 0)
sin05ang = 0;
sin05ang = copysign(sqrt(sin05ang), sig);
q *= SGQuat::fromRealImag(cos05ang, sin05ang*nto1);
return q;
}
// Return a quaternion which rotates the vector given by v
// to the vector -v. Other directions are *not* preserved.
static SGQuat fromChangeSign(const SGVec3<T>& v)
{
// The vector from points to the oposite direction than to.
// Find a vector perpendicular to the vector to.
T absv1 = fabs(v(0));
T absv2 = fabs(v(1));
T absv3 = fabs(v(2));
SGVec3<T> axis;
if (absv2 < absv1 && absv3 < absv1) {
T quot = v(1)/v(0);
axis = (1/sqrt(1+quot*quot))*SGVec3<T>(quot, -1, 0);
} else if (absv1 < absv2 && absv3 < absv2) {
T quot = v(2)/v(1);
axis = (1/sqrt(1+quot*quot))*SGVec3<T>(0, quot, -1);
} else if (absv1 < absv3 && absv2 < absv3) {
T quot = v(0)/v(2);
axis = (1/sqrt(1+quot*quot))*SGVec3<T>(-1, 0, quot);
} else {
// The all zero case.
return SGQuat::unit();
}
return SGQuat::fromRealImag(0, axis);
}
/// Return a quaternion from real and imaginary part
static SGQuat fromRealImag(T r, const SGVec3<T>& i)
{
SGQuat q;
q.w() = r;
q.x() = i.x();
q.y() = i.y();
q.z() = i.z();
return q;
}
/// Return an all zero vector
static SGQuat zeros(void)
{ return SGQuat(0, 0, 0, 0); }
/// write the euler angles into the references
void getEulerRad(T& zRad, T& yRad, T& xRad) const
{
T sqrQW = w()*w();
T sqrQX = x()*x();
T sqrQY = y()*y();
T sqrQZ = z()*z();
T num = 2*(y()*z() + w()*x());
T den = sqrQW - sqrQX - sqrQY + sqrQZ;
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();
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())
zRad = 0;
else {
T psi = atan2(num, den);
if (psi < 0)
psi += 2*SGMisc<T>::pi();
zRad = psi;
}
}
/// write the euler angles in degrees into the references
void getEulerDeg(T& zDeg, T& yDeg, T& xDeg) const
{
getEulerRad(zDeg, yDeg, xDeg);
zDeg = SGMisc<T>::rad2deg(zDeg);
yDeg = SGMisc<T>::rad2deg(yDeg);
xDeg = SGMisc<T>::rad2deg(xDeg);
}
/// write the angle axis representation into the references
void getAngleAxis(T& angle, SGVec3<T>& axis) const
{
T nrm = norm(*this);
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())
axis = SGVec3<T>(1, 0, 0);
else
axis = (rNrm/sAng)*imag(*this);
angle *= 2;
}
}
/// write the angle axis representation into the references
void getAngleAxis(SGVec3<T>& axis) const
{
T angle;
getAngleAxis(angle, axis);
axis *= angle;
}
/// Access by index, the index is unchecked
const T& operator()(unsigned i) const
{ return data()[i]; }
/// Access by index, the index is unchecked
T& operator()(unsigned i)
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
const T& operator[](unsigned i) const
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
T& operator[](unsigned i)
{ return data()[i]; }
/// Access the x component
const T& x(void) const
{ return data()[0]; }
/// Access the x component
T& x(void)
{ return data()[0]; }
/// Access the y component
const T& y(void) const
{ return data()[1]; }
/// Access the y component
T& y(void)
{ return data()[1]; }
/// Access the z component
const T& z(void) const
{ return data()[2]; }
/// Access the z component
T& z(void)
{ return data()[2]; }
/// Access the w component
const T& w(void) const
{ return data()[3]; }
/// Access the w component
T& w(void)
{ 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;
/// Inplace addition
SGQuat& operator+=(const SGQuat& v)
{ data()[0]+=v(0);data()[1]+=v(1);data()[2]+=v(2);data()[3]+=v(3);return *this; }
/// Inplace subtraction
SGQuat& operator-=(const SGQuat& v)
{ data()[0]-=v(0);data()[1]-=v(1);data()[2]-=v(2);data()[3]-=v(3);return *this; }
/// Inplace scalar multiplication
template<typename S>
SGQuat& operator*=(S s)
{ data()[0] *= s; data()[1] *= s; data()[2] *= s; data()[3] *= s; return *this; }
/// Inplace scalar multiplication by 1/s
template<typename S>
SGQuat& operator/=(S s)
{ return operator*=(1/T(s)); }
/// Inplace quaternion multiplication
SGQuat& operator*=(const SGQuat& v);
/// Transform a vector from the current coordinate frame to a coordinate
/// frame rotated with the quaternion
SGVec3<T> transform(const SGVec3<T>& v) const
{
T r = 2/dot(*this, *this);
SGVec3<T> qimag = imag(*this);
T qr = real(*this);
return (r*qr*qr - 1)*v + (r*dot(qimag, v))*qimag - (r*qr)*cross(qimag, v);
}
/// Transform a vector from the coordinate frame rotated with the quaternion
/// to the current coordinate frame
SGVec3<T> backTransform(const SGVec3<T>& v) const
{
T r = 2/dot(*this, *this);
SGVec3<T> qimag = imag(*this);
T qr = real(*this);
return (r*qr*qr - 1)*v + (r*dot(qimag, v))*qimag + (r*qr)*cross(qimag, v);
}
/// Rotate a given vector with the quaternion
SGVec3<T> rotate(const SGVec3<T>& v) const
{ return backTransform(v); }
/// Rotate a given vector with the inverse quaternion
SGVec3<T> rotateBack(const SGVec3<T>& v) const
{ return transform(v); }
/// Return the time derivative of the quaternion given the angular velocity
SGQuat
derivative(const SGVec3<T>& angVel) const
{
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));
return deriv;
}
private:
// Private because it assumes normalized inputs.
static SGQuat
fromRotateToSmaller90Deg(T cosang,
const SGVec3<T>& from, const SGVec3<T>& to)
{
// In this function we assume that the angle required to rotate from
// the vector from to the vector to is <= 90 deg.
// That is done so because of possible instabilities when we rotate more
// then 90deg.
// Note that the next comment does actually cover a *more* *general* case
// than we need in this function. That shows that this formula is even
// valid for rotations up to 180deg.
// Because of the signs in the axis, it is sufficient to care for angles
// 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);
// Now our assumption of angles <= 90 deg comes in play.
// For that reason, we know that cos05ang is not zero.
// It is even more, we can see from the above formula that
// sqrt(0.5) < cos05ang.
// Compute the rotation axis, that is
// sin(angle)*normalized rotation axis
SGVec3<T> axis = cross(to, from);
// We need sin(0.5*angle)*normalized rotation axis.
// So rescale with sin(0.5*x)/sin(x).
// To do that we use the equation:
// sin(x) = 2*sin(0.5*x)*cos(0.5*x)
return SGQuat::fromRealImag( cos05ang, (1/(2*cos05ang))*axis);
}
// Private because it assumes normalized inputs.
static SGQuat
fromRotateToNorm(const SGVec3<T>& from, const SGVec3<T>& to)
{
// To avoid instabilities with roundoff, we distinguish between rotations
// with more then 90deg and rotations with less than 90deg.
// Compute the cosine of the angle.
T cosang = dot(from, to);
// For the small ones do direct computation
if (T(-0.5) < cosang)
return SGQuat::fromRotateToSmaller90Deg(cosang, from, to);
// For larger rotations. first rotate from to -from.
// Past that we will have a smaller angle again.
SGQuat q1 = SGQuat::fromChangeSign(from);
SGQuat q2 = SGQuat::fromRotateToSmaller90Deg(-cosang, -from, to);
return q1*q2;
}
};
/// Unary +, do nothing ...
template<typename T>
inline
const SGQuat<T>&
operator+(const SGQuat<T>& v)
{ return v; }
/// Unary -, do nearly nothing
template<typename T>
inline
SGQuat<T>
operator-(const SGQuat<T>& v)
{ return SGQuat<T>(-v(0), -v(1), -v(2), -v(3)); }
/// Binary +
template<typename T>
inline
SGQuat<T>
operator+(const SGQuat<T>& v1, const SGQuat<T>& v2)
{ return SGQuat<T>(v1(0)+v2(0), v1(1)+v2(1), v1(2)+v2(2), v1(3)+v2(3)); }
/// Binary -
template<typename T>
inline
SGQuat<T>
operator-(const SGQuat<T>& v1, const SGQuat<T>& v2)
{ return SGQuat<T>(v1(0)-v2(0), v1(1)-v2(1), v1(2)-v2(2), v1(3)-v2(3)); }
/// Scalar multiplication
template<typename S, typename T>
inline
SGQuat<T>
operator*(S s, const SGQuat<T>& v)
{ return SGQuat<T>(s*v(0), s*v(1), s*v(2), s*v(3)); }
/// Scalar multiplication
template<typename S, typename T>
inline
SGQuat<T>
operator*(const SGQuat<T>& v, S s)
{ return SGQuat<T>(s*v(0), s*v(1), s*v(2), s*v(3)); }
/// Quaterion multiplication
template<typename T>
inline
SGQuat<T>
operator*(const SGQuat<T>& v1, const SGQuat<T>& v2)
{
SGQuat<T> v;
v.x() = v1.w()*v2.x() + v1.x()*v2.w() + v1.y()*v2.z() - v1.z()*v2.y();
v.y() = v1.w()*v2.y() - v1.x()*v2.z() + v1.y()*v2.w() + v1.z()*v2.x();
v.z() = v1.w()*v2.z() + v1.x()*v2.y() - v1.y()*v2.x() + v1.z()*v2.w();
v.w() = v1.w()*v2.w() - v1.x()*v2.x() - v1.y()*v2.y() - v1.z()*v2.z();
return v;
}
/// Now define the inplace multiplication
template<typename T>
inline
SGQuat<T>&
SGQuat<T>::operator*=(const SGQuat& v)
{ (*this) = (*this)*v; return *this; }
/// The conjugate of the quaternion, this is also the
/// inverse for normalized quaternions
template<typename T>
inline
SGQuat<T>
conj(const SGQuat<T>& v)
{ return SGQuat<T>(-v(0), -v(1), -v(2), v(3)); }
/// The conjugate of the quaternion, this is also the
/// inverse for normalized quaternions
template<typename T>
inline
SGQuat<T>
inverse(const SGQuat<T>& v)
{ return (1/dot(v, v))*SGQuat<T>(-v(0), -v(1), -v(2), v(3)); }
/// The imagniary part of the quaternion
template<typename T>
inline
T
real(const SGQuat<T>& v)
{ return v.w(); }
/// The imagniary part of the quaternion
template<typename T>
inline
SGVec3<T>
imag(const SGQuat<T>& v)
{ return SGVec3<T>(v.x(), v.y(), v.z()); }
/// Scalar dot product
template<typename T>
inline
T
dot(const SGQuat<T>& v1, const SGQuat<T>& v2)
{ return v1(0)*v2(0) + v1(1)*v2(1) + v1(2)*v2(2) + v1(3)*v2(3); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
T
norm(const SGQuat<T>& v)
{ return sqrt(dot(v, v)); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
T
length(const SGQuat<T>& v)
{ return sqrt(dot(v, v)); }
/// The 1-norm of the vector, this one is the fastest length function we
/// can implement on modern cpu's
template<typename T>
inline
T
norm1(const SGQuat<T>& v)
{ return fabs(v(0)) + fabs(v(1)) + fabs(v(2)) + fabs(v(3)); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
SGQuat<T>
normalize(const SGQuat<T>& q)
{ return (1/norm(q))*q; }
/// Return true if exactly the same
template<typename T>
inline
bool
operator==(const SGQuat<T>& v1, const SGQuat<T>& v2)
{ return v1(0)==v2(0) && v1(1)==v2(1) && v1(2)==v2(2) && v1(3)==v2(3); }
/// Return true if not exactly the same
template<typename T>
inline
bool
operator!=(const SGQuat<T>& v1, const SGQuat<T>& v2)
{ return ! (v1 == v2); }
/// Return true if equal to the relative tolerance tol
/// Note that this is not the same than comparing quaternions to represent
/// the same rotation
template<typename T>
inline
bool
equivalent(const SGQuat<T>& v1, const SGQuat<T>& v2, T tol)
{ return norm1(v1 - v2) < tol*(norm1(v1) + norm1(v2)); }
/// Return true if about equal to roundoff of the underlying type
/// Note that this is not the same than comparing quaternions to represent
/// the same rotation
template<typename T>
inline
bool
equivalent(const SGQuat<T>& v1, const SGQuat<T>& v2)
{ return equivalent(v1, v2, 100*SGLimits<T>::epsilon()); }
#ifndef NDEBUG
template<typename T>
inline
bool
isNaN(const SGQuat<T>& v)
{
return SGMisc<T>::isNaN(v(0)) || SGMisc<T>::isNaN(v(1))
|| SGMisc<T>::isNaN(v(2)) || SGMisc<T>::isNaN(v(3));
}
#endif
/// quaternion interpolation for t in [0,1] interpolate between src (=0)
/// and dst (=1)
template<typename T>
inline
SGQuat<T>
interpolate(T t, const SGQuat<T>& src, const SGQuat<T>& dst)
{
T cosPhi = dot(src, dst);
// need to take the shorter way ...
int signCosPhi = SGMisc<T>::sign(cosPhi);
// cosPhi must be corrected for that sign
cosPhi = fabs(cosPhi);
// first opportunity to fail - make sure acos will succeed later -
// result is correct
if (1 <= cosPhi)
return dst;
// now the half angle between the orientations
T o = acos(cosPhi);
// 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()) {
scale0 = 1 - t;
scale1 = t;
} else {
// note that we can give a positive lower bound for sin(o) here
T sino = sin(o);
T so = 1/sino;
scale0 = sin((1 - t)*o)*so;
scale1 = sin(t*o)*so;
}
return scale0*src + signCosPhi*scale1*dst;
}
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGQuat<T>& v)
{ return s << "[ " << v(0) << ", " << v(1) << ", " << v(2) << ", " << v(3) << " ]"; }
inline
SGQuatf
toQuatf(const SGQuatd& v)
{ return SGQuatf((float)v(0), (float)v(1), (float)v(2), (float)v(3)); }
inline
SGQuatd
toQuatd(const SGQuatf& v)
{ return SGQuatd(v(0), v(1), v(2), v(3)); }
#endif

62
simgear/math/SGRay.hxx Normal file
View File

@@ -0,0 +1,62 @@
// Copyright (C) 2006 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 SGRay_H
#define SGRay_H
template<typename T>
class SGRay {
public:
SGRay()
{ }
SGRay(const SGVec3<T>& origin, const SGVec3<T>& dir) :
_origin(origin), _direction(dir)
{ }
void set(const SGVec3<T>& origin, const SGVec3<T>& dir)
{ _origin = origin; _direction = dir; }
void setOrigin(const SGVec3<T>& origin)
{ _origin = origin; }
const SGVec3<T>& getOrigin() const
{ return _origin; }
void setDirection(const SGVec3<T>& direction)
{ _direction = direction; }
const SGVec3<T>& getDirection() const
{ return _direction; }
SGVec3<T> getNormalizedDirection() const
{ return normalize(getDirection()); }
private:
SGVec3<T> _origin;
SGVec3<T> _direction;
};
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s,
const SGRay<T>& ray)
{
return s << "ray: origin = " << ray.getOrigin()
<< ", direction = " << ray.getDirection();
}
#endif

87
simgear/math/SGSphere.hxx Normal file
View File

@@ -0,0 +1,87 @@
// Copyright (C) 2006 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 SGSphere_H
#define SGSphere_H
template<typename T>
class SGSphere {
public:
SGSphere() :
_radius(-1)
{ }
SGSphere(const SGVec3<T>& center, const T& radius) :
_center(center),
_radius(radius)
{ }
const SGVec3<T>& getCenter() const
{ return _center; }
void setCenter(const SGVec3<T>& center)
{ _center = center; }
const T& getRadius() const
{ return _radius; }
void setRadius(const T& radius)
{ _radius = radius; }
T getRadius2() const
{ return _radius*_radius; }
const bool empty() const
{ return !valid(); }
bool valid() const
{ return 0 <= _radius; }
void clear()
{ _radius = -1; }
void expandBy(const SGVec3<T>& v)
{
if (empty()) {
_center = v;
_radius = 0;
return;
}
T dist2 = distSqr(_center, v);
if (dist2 <= getRadius2())
return;
T dist = sqrt(dist2);
T newRadius = T(0.5)*(_radius + dist);
_center += ((newRadius - _radius)/dist)*(v - _center);
_radius = newRadius;
}
private:
SGVec3<T> _center;
T _radius;
};
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s,
const SGSphere<T>& sphere)
{
return s << "center = " << sphere.getCenter()
<< ", radius = " << sphere.getRadius();
}
#endif

101
simgear/math/SGTriangle.hxx Normal file
View File

@@ -0,0 +1,101 @@
// Copyright (C) 2006 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 SGTriangle_H
#define SGTrianlge_H
template<typename T>
class SGTriangle {
public:
SGTriangle()
{ }
SGTriangle(const SGVec3<T>& v0, const SGVec3<T>& v1, const SGVec3<T>& v2)
{ set(v0, v1, v2); }
SGTriangle(const SGVec3<T> v[3])
{ set(v); }
void set(const SGVec3<T>& v0, const SGVec3<T>& v1, const SGVec3<T>& v2)
{
_v0 = v0;
_d[0] = v1 - v0;
_d[1] = v2 - v0;
}
void set(const SGVec3<T> v[3])
{
_v0 = v[0];
_d[0] = v[1] - v[0];
_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();
}
// note that the index is unchecked
SGVec3<T> getVertex(unsigned i) const
{
if (0 < i)
return _v0 + _d[i-1];
return _v0;
}
/// return the normalized surface normal
SGVec3<T> getNormal() const
{ return normalize(cross(_d[0], _d[1])); }
const SGVec3<T>& getBaseVertex() const
{ return _v0; }
void setBaseVertex(const SGVec3<T>& v)
{ _v0 = v; }
const SGVec3<T>& getEdge(unsigned i) const
{ return _d[i]; }
void setEdge(unsigned i, const SGVec3<T>& d)
{ _d[i] = d; }
// flip the positive side
void flip()
{
SGVec3<T> tmp = _d[0];
_d[0] = _d[1];
_d[1] = tmp;
}
private:
/// Store one vertex directly, _d is the offset of the other two
/// vertices wrt the base vertex
/// For fast intersection tests this format prooves usefull. For that same
/// purpose also cache the cross product of the _d[i].
SGVec3<T> _v0;
SGVec3<T> _d[2];
};
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s,
const SGTriangle<T>& triangle)
{
return s << "triangle: v0 = " << triangle.getVertex(0)
<< ", v1 = " << triangle.getVertex(1)
<< ", v2 = " << triangle.getVertex(2);
}
#endif

405
simgear/math/SGVec2.hxx Normal file
View File

@@ -0,0 +1,405 @@
// Copyright (C) 2006 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 SGVec2_H
#define SGVec2_H
#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; }
};
/// 2D Vector Class
template<typename T>
class SGVec2 : protected SGVec2Storage<T> {
public:
typedef T value_type;
/// Default constructor. Does not initialize at all.
/// If you need them zero initialized, use SGVec2::zeros()
SGVec2(void)
{
/// Initialize with nans in the debug build, that will guarantee to have
/// a fast uninitialized default constructor in the release but shows up
/// uninitialized values in the debug build very fast ...
#ifndef NDEBUG
for (unsigned i = 0; i < 2; ++i)
data()[i] = SGLimits<T>::quiet_NaN();
#endif
}
/// Constructor. Initialize by the given values
SGVec2(T x, T y)
{ data()[0] = x; data()[1] = y; }
/// Constructor. Initialize by the content of a plain array,
/// 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)
{ data()[0] = d[0]; data()[1] = d[1]; }
/// Access by index, the index is unchecked
const T& operator()(unsigned i) const
{ return data()[i]; }
/// Access by index, the index is unchecked
T& operator()(unsigned i)
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
const T& operator[](unsigned i) const
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
T& operator[](unsigned i)
{ return data()[i]; }
/// Access the x component
const T& x(void) const
{ return data()[0]; }
/// Access the x component
T& x(void)
{ return data()[0]; }
/// Access the y component
const T& y(void) const
{ return data()[1]; }
/// Access the y component
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;
/// Inplace addition
SGVec2& operator+=(const SGVec2& v)
{ data()[0] += v(0); data()[1] += v(1); return *this; }
/// Inplace subtraction
SGVec2& operator-=(const SGVec2& v)
{ data()[0] -= v(0); data()[1] -= v(1); return *this; }
/// Inplace scalar multiplication
template<typename S>
SGVec2& operator*=(S s)
{ data()[0] *= s; data()[1] *= s; return *this; }
/// Inplace scalar multiplication by 1/s
template<typename S>
SGVec2& operator/=(S s)
{ return operator*=(1/T(s)); }
/// Return an all zero vector
static SGVec2 zeros(void)
{ return SGVec2(0, 0); }
/// Return unit vectors
static SGVec2 e1(void)
{ return SGVec2(1, 0); }
static SGVec2 e2(void)
{ return SGVec2(0, 1); }
};
/// Unary +, do nothing ...
template<typename T>
inline
const SGVec2<T>&
operator+(const SGVec2<T>& v)
{ return v; }
/// Unary -, do nearly nothing
template<typename T>
inline
SGVec2<T>
operator-(const SGVec2<T>& v)
{ return SGVec2<T>(-v(0), -v(1)); }
/// Binary +
template<typename T>
inline
SGVec2<T>
operator+(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return SGVec2<T>(v1(0)+v2(0), v1(1)+v2(1)); }
/// Binary -
template<typename T>
inline
SGVec2<T>
operator-(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return SGVec2<T>(v1(0)-v2(0), v1(1)-v2(1)); }
/// Scalar multiplication
template<typename S, typename T>
inline
SGVec2<T>
operator*(S s, const SGVec2<T>& v)
{ return SGVec2<T>(s*v(0), s*v(1)); }
/// Scalar multiplication
template<typename S, typename T>
inline
SGVec2<T>
operator*(const SGVec2<T>& v, S s)
{ return SGVec2<T>(s*v(0), s*v(1)); }
/// multiplication as a multiplicator, that is assume that the first vector
/// represents a 2x2 diagonal matrix with the diagonal elements in the vector.
/// Then the result is the product of that matrix times the second vector.
template<typename T>
inline
SGVec2<T>
mult(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return SGVec2<T>(v1(0)*v2(0), v1(1)*v2(1)); }
/// component wise min
template<typename T>
inline
SGVec2<T>
min(const SGVec2<T>& v1, const SGVec2<T>& v2)
{return SGVec2<T>(SGMisc<T>::min(v1(0), v2(0)), SGMisc<T>::min(v1(1), v2(1)));}
template<typename S, typename T>
inline
SGVec2<T>
min(const SGVec2<T>& v, S s)
{ return SGVec2<T>(SGMisc<T>::min(s, v(0)), SGMisc<T>::min(s, v(1))); }
template<typename S, typename T>
inline
SGVec2<T>
min(S s, const SGVec2<T>& v)
{ return SGVec2<T>(SGMisc<T>::min(s, v(0)), SGMisc<T>::min(s, v(1))); }
/// component wise max
template<typename T>
inline
SGVec2<T>
max(const SGVec2<T>& v1, const SGVec2<T>& v2)
{return SGVec2<T>(SGMisc<T>::max(v1(0), v2(0)), SGMisc<T>::max(v1(1), v2(1)));}
template<typename S, typename T>
inline
SGVec2<T>
max(const SGVec2<T>& v, S s)
{ return SGVec2<T>(SGMisc<T>::max(s, v(0)), SGMisc<T>::max(s, v(1))); }
template<typename S, typename T>
inline
SGVec2<T>
max(S s, const SGVec2<T>& v)
{ return SGVec2<T>(SGMisc<T>::max(s, v(0)), SGMisc<T>::max(s, v(1))); }
/// Scalar dot product
template<typename T>
inline
T
dot(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return v1(0)*v2(0) + v1(1)*v2(1); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
T
norm(const SGVec2<T>& v)
{ return sqrt(dot(v, v)); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
T
length(const SGVec2<T>& v)
{ return sqrt(dot(v, v)); }
/// The 1-norm of the vector, this one is the fastest length function we
/// can implement on modern cpu's
template<typename T>
inline
T
norm1(const SGVec2<T>& v)
{ return fabs(v(0)) + fabs(v(1)); }
/// The inf-norm of the vector
template<typename T>
inline
T
normI(const SGVec2<T>& v)
{ return SGMisc<T>::max(fabs(v(0)), fabs(v(1))); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
SGVec2<T>
normalize(const SGVec2<T>& v)
{ return (1/norm(v))*v; }
/// Return true if exactly the same
template<typename T>
inline
bool
operator==(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return v1(0) == v2(0) && v1(1) == v2(1); }
/// Return true if not exactly the same
template<typename T>
inline
bool
operator!=(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return ! (v1 == v2); }
/// Return true if smaller, good for putting that into a std::map
template<typename T>
inline
bool
operator<(const SGVec2<T>& v1, const SGVec2<T>& v2)
{
if (v1(0) < v2(0)) return true;
else if (v2(0) < v1(0)) return false;
else return (v1(1) < v2(1));
}
template<typename T>
inline
bool
operator<=(const SGVec2<T>& v1, const SGVec2<T>& v2)
{
if (v1(0) < v2(0)) return true;
else if (v2(0) < v1(0)) return false;
else return (v1(1) <= v2(1));
}
template<typename T>
inline
bool
operator>(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return operator<(v2, v1); }
template<typename T>
inline
bool
operator>=(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return operator<=(v2, v1); }
/// Return true if equal to the relative tolerance tol
template<typename T>
inline
bool
equivalent(const SGVec2<T>& v1, const SGVec2<T>& v2, T rtol, T atol)
{ return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)) + atol; }
/// Return true if equal to the relative tolerance tol
template<typename T>
inline
bool
equivalent(const SGVec2<T>& v1, const SGVec2<T>& v2, T rtol)
{ return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)); }
/// Return true if about equal to roundoff of the underlying type
template<typename T>
inline
bool
equivalent(const SGVec2<T>& v1, const SGVec2<T>& v2)
{
T tol = 100*SGLimits<T>::epsilon();
return equivalent(v1, v2, tol, tol);
}
/// The euclidean distance of the two vectors
template<typename T>
inline
T
dist(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ return norm(v1 - v2); }
/// The squared euclidean distance of the two vectors
template<typename T>
inline
T
distSqr(const SGVec2<T>& v1, const SGVec2<T>& v2)
{ SGVec2<T> tmp = v1 - v2; return dot(tmp, tmp); }
#ifndef NDEBUG
template<typename T>
inline
bool
isNaN(const SGVec2<T>& v)
{
return SGMisc<T>::isNaN(v(0)) || SGMisc<T>::isNaN(v(1));
}
#endif
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGVec2<T>& v)
{ return s << "[ " << v(0) << ", " << v(1) << " ]"; }
inline
SGVec2f
toVec2f(const SGVec2d& v)
{ return SGVec2f((float)v(0), (float)v(1)); }
inline
SGVec2d
toVec2d(const SGVec2f& v)
{ return SGVec2d(v(0), v(1)); }
#endif

527
simgear/math/SGVec3.hxx Normal file
View File

@@ -0,0 +1,527 @@
// Copyright (C) 2006 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 SGVec3_H
#define SGVec3_H
#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; }
};
/// 3D Vector Class
template<typename T>
class SGVec3 : protected SGVec3Storage<T> {
public:
typedef T value_type;
/// Default constructor. Does not initialize at all.
/// If you need them zero initialized, use SGVec3::zeros()
SGVec3(void)
{
/// Initialize with nans in the debug build, that will guarantee to have
/// a fast uninitialized default constructor in the release but shows up
/// uninitialized values in the debug build very fast ...
#ifndef NDEBUG
for (unsigned i = 0; i < 3; ++i)
data()[i] = SGLimits<T>::quiet_NaN();
#endif
}
/// Constructor. Initialize by the given values
SGVec3(T x, T y, T z)
{ data()[0] = x; data()[1] = y; data()[2] = z; }
/// Constructor. Initialize by the content of a plain array,
/// 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)
{ 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; }
/// Access by index, the index is unchecked
const T& operator()(unsigned i) const
{ return data()[i]; }
/// Access by index, the index is unchecked
T& operator()(unsigned i)
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
const T& operator[](unsigned i) const
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
T& operator[](unsigned i)
{ return data()[i]; }
/// Access the x component
const T& x(void) const
{ return data()[0]; }
/// Access the x component
T& x(void)
{ return data()[0]; }
/// Access the y component
const T& y(void) const
{ return data()[1]; }
/// Access the y component
T& y(void)
{ return data()[1]; }
/// Access the z component
const T& z(void) const
{ return data()[2]; }
/// Access the z component
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;
/// Inplace addition
SGVec3& operator+=(const SGVec3& v)
{ data()[0] += v(0); data()[1] += v(1); data()[2] += v(2); return *this; }
/// Inplace subtraction
SGVec3& operator-=(const SGVec3& v)
{ data()[0] -= v(0); data()[1] -= v(1); data()[2] -= v(2); return *this; }
/// Inplace scalar multiplication
template<typename S>
SGVec3& operator*=(S s)
{ data()[0] *= s; data()[1] *= s; data()[2] *= s; return *this; }
/// Inplace scalar multiplication by 1/s
template<typename S>
SGVec3& operator/=(S s)
{ return operator*=(1/T(s)); }
/// Return an all zero vector
static SGVec3 zeros(void)
{ return SGVec3(0, 0, 0); }
/// Return unit vectors
static SGVec3 e1(void)
{ return SGVec3(1, 0, 0); }
static SGVec3 e2(void)
{ return SGVec3(0, 1, 0); }
static SGVec3 e3(void)
{ return SGVec3(0, 0, 1); }
/// Constructor. Initialize by a geodetic coordinate
/// Note that this conversion is relatively expensive to compute
static SGVec3 fromGeod(const SGGeod& geod);
/// Constructor. Initialize by a geocentric coordinate
/// Note that this conversion is relatively expensive to compute
static SGVec3 fromGeoc(const SGGeoc& geoc);
};
template<>
inline
SGVec3<double>
SGVec3<double>::fromGeod(const SGGeod& geod)
{
SGVec3<double> cart;
SGGeodesy::SGGeodToCart(geod, cart);
return cart;
}
template<>
inline
SGVec3<float>
SGVec3<float>::fromGeod(const SGGeod& geod)
{
SGVec3<double> cart;
SGGeodesy::SGGeodToCart(geod, cart);
return SGVec3<float>(cart(0), cart(1), cart(2));
}
template<>
inline
SGVec3<double>
SGVec3<double>::fromGeoc(const SGGeoc& geoc)
{
SGVec3<double> cart;
SGGeodesy::SGGeocToCart(geoc, cart);
return cart;
}
template<>
inline
SGVec3<float>
SGVec3<float>::fromGeoc(const SGGeoc& geoc)
{
SGVec3<double> cart;
SGGeodesy::SGGeocToCart(geoc, cart);
return SGVec3<float>(cart(0), cart(1), cart(2));
}
/// Unary +, do nothing ...
template<typename T>
inline
const SGVec3<T>&
operator+(const SGVec3<T>& v)
{ return v; }
/// Unary -, do nearly nothing
template<typename T>
inline
SGVec3<T>
operator-(const SGVec3<T>& v)
{ return SGVec3<T>(-v(0), -v(1), -v(2)); }
/// Binary +
template<typename T>
inline
SGVec3<T>
operator+(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ return SGVec3<T>(v1(0)+v2(0), v1(1)+v2(1), v1(2)+v2(2)); }
/// Binary -
template<typename T>
inline
SGVec3<T>
operator-(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ return SGVec3<T>(v1(0)-v2(0), v1(1)-v2(1), v1(2)-v2(2)); }
/// Scalar multiplication
template<typename S, typename T>
inline
SGVec3<T>
operator*(S s, const SGVec3<T>& v)
{ return SGVec3<T>(s*v(0), s*v(1), s*v(2)); }
/// Scalar multiplication
template<typename S, typename T>
inline
SGVec3<T>
operator*(const SGVec3<T>& v, S s)
{ return SGVec3<T>(s*v(0), s*v(1), s*v(2)); }
/// multiplication as a multiplicator, that is assume that the first vector
/// represents a 3x3 diagonal matrix with the diagonal elements in the vector.
/// Then the result is the product of that matrix times the second vector.
template<typename T>
inline
SGVec3<T>
mult(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ return SGVec3<T>(v1(0)*v2(0), v1(1)*v2(1), v1(2)*v2(2)); }
/// component wise min
template<typename T>
inline
SGVec3<T>
min(const SGVec3<T>& v1, const SGVec3<T>& v2)
{
return SGVec3<T>(SGMisc<T>::min(v1(0), v2(0)),
SGMisc<T>::min(v1(1), v2(1)),
SGMisc<T>::min(v1(2), v2(2)));
}
template<typename S, typename T>
inline
SGVec3<T>
min(const SGVec3<T>& v, S s)
{
return SGVec3<T>(SGMisc<T>::min(s, v(0)),
SGMisc<T>::min(s, v(1)),
SGMisc<T>::min(s, v(2)));
}
template<typename S, typename T>
inline
SGVec3<T>
min(S s, const SGVec3<T>& v)
{
return SGVec3<T>(SGMisc<T>::min(s, v(0)),
SGMisc<T>::min(s, v(1)),
SGMisc<T>::min(s, v(2)));
}
/// component wise max
template<typename T>
inline
SGVec3<T>
max(const SGVec3<T>& v1, const SGVec3<T>& v2)
{
return SGVec3<T>(SGMisc<T>::max(v1(0), v2(0)),
SGMisc<T>::max(v1(1), v2(1)),
SGMisc<T>::max(v1(2), v2(2)));
}
template<typename S, typename T>
inline
SGVec3<T>
max(const SGVec3<T>& v, S s)
{
return SGVec3<T>(SGMisc<T>::max(s, v(0)),
SGMisc<T>::max(s, v(1)),
SGMisc<T>::max(s, v(2)));
}
template<typename S, typename T>
inline
SGVec3<T>
max(S s, const SGVec3<T>& v)
{
return SGVec3<T>(SGMisc<T>::max(s, v(0)),
SGMisc<T>::max(s, v(1)),
SGMisc<T>::max(s, v(2)));
}
/// Scalar dot product
template<typename T>
inline
T
dot(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ return v1(0)*v2(0) + v1(1)*v2(1) + v1(2)*v2(2); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
T
norm(const SGVec3<T>& v)
{ return sqrt(dot(v, v)); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
T
length(const SGVec3<T>& v)
{ return sqrt(dot(v, v)); }
/// The 1-norm of the vector, this one is the fastest length function we
/// can implement on modern cpu's
template<typename T>
inline
T
norm1(const SGVec3<T>& v)
{ return fabs(v(0)) + fabs(v(1)) + fabs(v(2)); }
/// The inf-norm of the vector
template<typename T>
inline
T
normI(const SGVec3<T>& v)
{ return SGMisc<T>::max(fabs(v(0)), fabs(v(1)), fabs(v(2))); }
/// Vector cross product
template<typename T>
inline
SGVec3<T>
cross(const SGVec3<T>& v1, const SGVec3<T>& v2)
{
return SGVec3<T>(v1(1)*v2(2) - v1(2)*v2(1),
v1(2)*v2(0) - v1(0)*v2(2),
v1(0)*v2(1) - v1(1)*v2(0));
}
/// return any normalized vector perpendicular to v
template<typename T>
inline
SGVec3<T>
perpendicular(const SGVec3<T>& v)
{
T absv1 = fabs(v(0));
T absv2 = fabs(v(1));
T absv3 = fabs(v(2));
if (absv2 < absv1 && absv3 < absv1) {
T quot = v(1)/v(0);
return (1/sqrt(1+quot*quot))*SGVec3<T>(quot, -1, 0);
} else if (absv3 < absv2) {
T quot = v(2)/v(1);
return (1/sqrt(1+quot*quot))*SGVec3<T>(0, quot, -1);
} else if (SGLimits<T>::min() < absv3) {
T quot = v(0)/v(2);
return (1/sqrt(1+quot*quot))*SGVec3<T>(-1, 0, quot);
} else {
// the all zero case ...
return SGVec3<T>(0, 0, 0);
}
}
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
SGVec3<T>
normalize(const SGVec3<T>& v)
{ return (1/norm(v))*v; }
/// Return true if exactly the same
template<typename T>
inline
bool
operator==(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ return v1(0) == v2(0) && v1(1) == v2(1) && v1(2) == v2(2); }
/// Return true if not exactly the same
template<typename T>
inline
bool
operator!=(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ return ! (v1 == v2); }
/// Return true if smaller, good for putting that into a std::map
template<typename T>
inline
bool
operator<(const SGVec3<T>& v1, const SGVec3<T>& v2)
{
if (v1(0) < v2(0)) return true;
else if (v2(0) < v1(0)) return false;
else if (v1(1) < v2(1)) return true;
else if (v2(1) < v1(1)) return false;
else return (v1(2) < v2(2));
}
template<typename T>
inline
bool
operator<=(const SGVec3<T>& v1, const SGVec3<T>& v2)
{
if (v1(0) < v2(0)) return true;
else if (v2(0) < v1(0)) return false;
else if (v1(1) < v2(1)) return true;
else if (v2(1) < v1(1)) return false;
else return (v1(2) <= v2(2));
}
template<typename T>
inline
bool
operator>(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ return operator<(v2, v1); }
template<typename T>
inline
bool
operator>=(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ return operator<=(v2, v1); }
/// Return true if equal to the relative tolerance tol
template<typename T>
inline
bool
equivalent(const SGVec3<T>& v1, const SGVec3<T>& v2, T rtol, T atol)
{ return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)) + atol; }
/// Return true if equal to the relative tolerance tol
template<typename T>
inline
bool
equivalent(const SGVec3<T>& v1, const SGVec3<T>& v2, T rtol)
{ return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)); }
/// Return true if about equal to roundoff of the underlying type
template<typename T>
inline
bool
equivalent(const SGVec3<T>& v1, const SGVec3<T>& v2)
{
T tol = 100*SGLimits<T>::epsilon();
return equivalent(v1, v2, tol, tol);
}
/// The euclidean distance of the two vectors
template<typename T>
inline
T
dist(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ return norm(v1 - v2); }
/// The squared euclidean distance of the two vectors
template<typename T>
inline
T
distSqr(const SGVec3<T>& v1, const SGVec3<T>& v2)
{ SGVec3<T> tmp = v1 - v2; return dot(tmp, tmp); }
#ifndef NDEBUG
template<typename T>
inline
bool
isNaN(const SGVec3<T>& v)
{
return SGMisc<T>::isNaN(v(0)) ||
SGMisc<T>::isNaN(v(1)) || SGMisc<T>::isNaN(v(2));
}
#endif
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGVec3<T>& v)
{ return s << "[ " << v(0) << ", " << v(1) << ", " << v(2) << " ]"; }
inline
SGVec3f
toVec3f(const SGVec3d& v)
{ return SGVec3f((float)v(0), (float)v(1), (float)v(2)); }
inline
SGVec3d
toVec3d(const SGVec3f& v)
{ return SGVec3d(v(0), v(1), v(2)); }
#endif

463
simgear/math/SGVec4.hxx Normal file
View File

@@ -0,0 +1,463 @@
// Copyright (C) 2006 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 SGVec4_H
#define SGVec4_H
#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; }
};
/// 4D Vector Class
template<typename T>
class SGVec4 : protected SGVec4Storage<T> {
public:
typedef T value_type;
/// Default constructor. Does not initialize at all.
/// If you need them zero initialized, use SGVec4::zeros()
SGVec4(void)
{
/// Initialize with nans in the debug build, that will guarantee to have
/// a fast uninitialized default constructor in the release but shows up
/// uninitialized values in the debug build very fast ...
#ifndef NDEBUG
for (unsigned i = 0; i < 4; ++i)
data()[i] = SGLimits<T>::quiet_NaN();
#endif
}
/// Constructor. Initialize by the given values
SGVec4(T x, T y, T z, T w)
{ data()[0] = x; data()[1] = y; data()[2] = z; data()[3] = w; }
/// Constructor. Initialize by the content of a plain array,
/// 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)
{ 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]; }
/// Access by index, the index is unchecked
T& operator()(unsigned i)
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
const T& operator[](unsigned i) const
{ return data()[i]; }
/// Access raw data by index, the index is unchecked
T& operator[](unsigned i)
{ return data()[i]; }
/// Access the x component
const T& x(void) const
{ return data()[0]; }
/// Access the x component
T& x(void)
{ return data()[0]; }
/// Access the y component
const T& y(void) const
{ return data()[1]; }
/// Access the y component
T& y(void)
{ return data()[1]; }
/// Access the z component
const T& z(void) const
{ return data()[2]; }
/// Access the z component
T& z(void)
{ return data()[2]; }
/// Access the x component
const T& w(void) const
{ return data()[3]; }
/// Access the x component
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;
/// Inplace addition
SGVec4& operator+=(const SGVec4& v)
{ data()[0]+=v(0);data()[1]+=v(1);data()[2]+=v(2);data()[3]+=v(3);return *this; }
/// Inplace subtraction
SGVec4& operator-=(const SGVec4& v)
{ data()[0]-=v(0);data()[1]-=v(1);data()[2]-=v(2);data()[3]-=v(3);return *this; }
/// Inplace scalar multiplication
template<typename S>
SGVec4& operator*=(S s)
{ data()[0] *= s; data()[1] *= s; data()[2] *= s; data()[3] *= s; return *this; }
/// Inplace scalar multiplication by 1/s
template<typename S>
SGVec4& operator/=(S s)
{ return operator*=(1/T(s)); }
/// Return an all zero vector
static SGVec4 zeros(void)
{ return SGVec4(0, 0, 0, 0); }
/// Return unit vectors
static SGVec4 e1(void)
{ return SGVec4(1, 0, 0, 0); }
static SGVec4 e2(void)
{ return SGVec4(0, 1, 0, 0); }
static SGVec4 e3(void)
{ return SGVec4(0, 0, 1, 0); }
static SGVec4 e4(void)
{ return SGVec4(0, 0, 0, 1); }
};
/// Unary +, do nothing ...
template<typename T>
inline
const SGVec4<T>&
operator+(const SGVec4<T>& v)
{ return v; }
/// Unary -, do nearly nothing
template<typename T>
inline
SGVec4<T>
operator-(const SGVec4<T>& v)
{ return SGVec4<T>(-v(0), -v(1), -v(2), -v(3)); }
/// Binary +
template<typename T>
inline
SGVec4<T>
operator+(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ return SGVec4<T>(v1(0)+v2(0), v1(1)+v2(1), v1(2)+v2(2), v1(3)+v2(3)); }
/// Binary -
template<typename T>
inline
SGVec4<T>
operator-(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ return SGVec4<T>(v1(0)-v2(0), v1(1)-v2(1), v1(2)-v2(2), v1(3)-v2(3)); }
/// Scalar multiplication
template<typename S, typename T>
inline
SGVec4<T>
operator*(S s, const SGVec4<T>& v)
{ return SGVec4<T>(s*v(0), s*v(1), s*v(2), s*v(3)); }
/// Scalar multiplication
template<typename S, typename T>
inline
SGVec4<T>
operator*(const SGVec4<T>& v, S s)
{ return SGVec4<T>(s*v(0), s*v(1), s*v(2), s*v(3)); }
/// multiplication as a multiplicator, that is assume that the first vector
/// represents a 4x4 diagonal matrix with the diagonal elements in the vector.
/// Then the result is the product of that matrix times the second vector.
template<typename T>
inline
SGVec4<T>
mult(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ return SGVec4<T>(v1(0)*v2(0), v1(1)*v2(1), v1(2)*v2(2), v1(3)*v2(3)); }
/// component wise min
template<typename T>
inline
SGVec4<T>
min(const SGVec4<T>& v1, const SGVec4<T>& v2)
{
return SGVec4<T>(SGMisc<T>::min(v1(0), v2(0)),
SGMisc<T>::min(v1(1), v2(1)),
SGMisc<T>::min(v1(2), v2(2)),
SGMisc<T>::min(v1(3), v2(3)));
}
template<typename S, typename T>
inline
SGVec4<T>
min(const SGVec4<T>& v, S s)
{
return SGVec4<T>(SGMisc<T>::min(s, v(0)),
SGMisc<T>::min(s, v(1)),
SGMisc<T>::min(s, v(2)),
SGMisc<T>::min(s, v(3)));
}
template<typename S, typename T>
inline
SGVec4<T>
min(S s, const SGVec4<T>& v)
{
return SGVec4<T>(SGMisc<T>::min(s, v(0)),
SGMisc<T>::min(s, v(1)),
SGMisc<T>::min(s, v(2)),
SGMisc<T>::min(s, v(3)));
}
/// component wise max
template<typename T>
inline
SGVec4<T>
max(const SGVec4<T>& v1, const SGVec4<T>& v2)
{
return SGVec4<T>(SGMisc<T>::max(v1(0), v2(0)),
SGMisc<T>::max(v1(1), v2(1)),
SGMisc<T>::max(v1(2), v2(2)),
SGMisc<T>::max(v1(3), v2(3)));
}
template<typename S, typename T>
inline
SGVec4<T>
max(const SGVec4<T>& v, S s)
{
return SGVec4<T>(SGMisc<T>::max(s, v(0)),
SGMisc<T>::max(s, v(1)),
SGMisc<T>::max(s, v(2)),
SGMisc<T>::max(s, v(3)));
}
template<typename S, typename T>
inline
SGVec4<T>
max(S s, const SGVec4<T>& v)
{
return SGVec4<T>(SGMisc<T>::max(s, v(0)),
SGMisc<T>::max(s, v(1)),
SGMisc<T>::max(s, v(2)),
SGMisc<T>::max(s, v(3)));
}
/// Scalar dot product
template<typename T>
inline
T
dot(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ return v1(0)*v2(0) + v1(1)*v2(1) + v1(2)*v2(2) + v1(3)*v2(3); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
T
norm(const SGVec4<T>& v)
{ return sqrt(dot(v, v)); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
T
length(const SGVec4<T>& v)
{ return sqrt(dot(v, v)); }
/// The 1-norm of the vector, this one is the fastest length function we
/// can implement on modern cpu's
template<typename T>
inline
T
norm1(const SGVec4<T>& v)
{ return fabs(v(0)) + fabs(v(1)) + fabs(v(2)) + fabs(v(3)); }
/// The inf-norm of the vector
template<typename T>
inline
T
normI(const SGVec4<T>& v)
{ return SGMisc<T>::max(fabs(v(0)), fabs(v(1)), fabs(v(2)), fabs(v(2))); }
/// The euclidean norm of the vector, that is what most people call length
template<typename T>
inline
SGVec4<T>
normalize(const SGVec4<T>& v)
{ return (1/norm(v))*v; }
/// Return true if exactly the same
template<typename T>
inline
bool
operator==(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ return v1(0)==v2(0) && v1(1)==v2(1) && v1(2)==v2(2) && v1(3)==v2(3); }
/// Return true if not exactly the same
template<typename T>
inline
bool
operator!=(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ return ! (v1 == v2); }
/// Return true if smaller, good for putting that into a std::map
template<typename T>
inline
bool
operator<(const SGVec4<T>& v1, const SGVec4<T>& v2)
{
if (v1(0) < v2(0)) return true;
else if (v2(0) < v1(0)) return false;
else if (v1(1) < v2(1)) return true;
else if (v2(1) < v1(1)) return false;
else if (v1(2) < v2(2)) return true;
else if (v2(2) < v1(2)) return false;
else return (v1(3) < v2(3));
}
template<typename T>
inline
bool
operator<=(const SGVec4<T>& v1, const SGVec4<T>& v2)
{
if (v1(0) < v2(0)) return true;
else if (v2(0) < v1(0)) return false;
else if (v1(1) < v2(1)) return true;
else if (v2(1) < v1(1)) return false;
else if (v1(2) < v2(2)) return true;
else if (v2(2) < v1(2)) return false;
else return (v1(3) <= v2(3));
}
template<typename T>
inline
bool
operator>(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ return operator<(v2, v1); }
template<typename T>
inline
bool
operator>=(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ return operator<=(v2, v1); }
/// Return true if equal to the relative tolerance tol
template<typename T>
inline
bool
equivalent(const SGVec4<T>& v1, const SGVec4<T>& v2, T rtol, T atol)
{ return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)) + atol; }
/// Return true if equal to the relative tolerance tol
template<typename T>
inline
bool
equivalent(const SGVec4<T>& v1, const SGVec4<T>& v2, T rtol)
{ return norm1(v1 - v2) < rtol*(norm1(v1) + norm1(v2)); }
/// Return true if about equal to roundoff of the underlying type
template<typename T>
inline
bool
equivalent(const SGVec4<T>& v1, const SGVec4<T>& v2)
{
T tol = 100*SGLimits<T>::epsilon();
return equivalent(v1, v2, tol, tol);
}
/// The euclidean distance of the two vectors
template<typename T>
inline
T
dist(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ return norm(v1 - v2); }
/// The squared euclidean distance of the two vectors
template<typename T>
inline
T
distSqr(const SGVec4<T>& v1, const SGVec4<T>& v2)
{ SGVec4<T> tmp = v1 - v2; return dot(tmp, tmp); }
#ifndef NDEBUG
template<typename T>
inline
bool
isNaN(const SGVec4<T>& v)
{
return SGMisc<T>::isNaN(v(0)) || SGMisc<T>::isNaN(v(1))
|| SGMisc<T>::isNaN(v(2)) || SGMisc<T>::isNaN(v(3));
}
#endif
/// Output to an ostream
template<typename char_type, typename traits_type, typename T>
inline
std::basic_ostream<char_type, traits_type>&
operator<<(std::basic_ostream<char_type, traits_type>& s, const SGVec4<T>& v)
{ return s << "[ " << v(0) << ", " << v(1) << ", " << v(2) << ", " << v(3) << " ]"; }
inline
SGVec4f
toVec4f(const SGVec4d& v)
{ return SGVec4f((float)v(0), (float)v(1), (float)v(2), (float)v(3)); }
inline
SGVec4d
toVec4d(const SGVec4f& v)
{ return SGVec4d(v(0), v(1), v(2), v(3)); }
#endif

View File

@@ -1,291 +0,0 @@
/*
* \file fastmath.cxx
* fast mathematics routines.
*
* Refferences:
*
* A Fast, Compact Approximation of the Exponential Function
* Nicol N. Schraudolph
* IDSIA, Lugano, Switzerland
* http://www.inf.ethz.ch/~schraudo/pubs/exp.pdf
*
* Base-2 exp, Laurent de Soras
* http://www.musicdsp.org/archive.php?classid=5#106
*
* Fast log() Function, by Laurent de Soras:
* http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-Fastlogfunction&forum=totd&id=-1
*
* Sin, Cos, Tan approximation
* http://www.musicdsp.org/showArchiveComment.php?ArchiveID=115
*
* fast floating point power computation:
* http://playstation2-linux.com/download/adam/power.c
*/
/*
* $Id$
*/
#include <simgear/constants.h>
#include "fastmath.hxx"
/**
* This function is on avarage 9 times faster than the system exp() function
* and has an error of about 1.5%
*/
static union {
double d;
struct {
#if BYTE_ORDER == BIG_ENDIAN
int i, j;
#else
int j, i;
#endif
} n;
} _eco;
double fast_exp(double val) {
const double a = 1048576/M_LN2;
const double b_c = 1072632447; /* 1072693248 - 60801 */
_eco.n.i = (int)(a*val + b_c);
return _eco.d;
}
/*
* Linear approx. between 2 integer values of val. Uses 32-bit integers.
* Not very efficient but faster than exp()
*/
double fast_exp2( const double val )
{
int e;
double ret;
if (val >= 0) {
e = int (val);
ret = val - (e - 1);
#if BYTE_ORDER == BIG_ENDIAN
((*((int *) &ret)) &= ~(2047 << 20)) += (e + 1023) << 20;
#else
((*(1 + (int *) &ret)) &= ~(2047 << 20)) += (e + 1023) << 20;
#endif
} else {
e = int (val + 1023);
ret = val - (e - 1024);
#if BYTE_ORDER == BIG_ENDIAN
((*((int *) &ret)) &= ~(2047 << 20)) += e << 20;
#else
((*(1 + (int *) &ret)) &= ~(2047 << 20)) += e << 20;
#endif
}
return ret;
}
/*
*
*/
float _fast_log2(const float val)
{
float result, tmp;
float mp = 0.346607f;
result = *(int*)&val;
result *= 1.0/(1<<23);
result = result - 127;
tmp = result - floor(result);
tmp = (tmp - tmp*tmp) * mp;
return tmp + result;
}
float _fast_pow2(const float val)
{
float result;
float mp = 0.33971f;
float tmp = val - floor(val);
tmp = (tmp - tmp*tmp) * mp;
result = val + 127 - tmp;
result *= (1<<23);
*(int*)&result = (int)result;
return result;
}
/**
* While we're on the subject, someone might have use for these as well?
* Float Shift Left and Float Shift Right. Do what you want with this.
*/
void fast_BSL(float &x, register unsigned long shiftAmount) {
*(unsigned long*)&x+=shiftAmount<<23;
}
void fast_BSR(float &x, register unsigned long shiftAmount) {
*(unsigned long*)&x-=shiftAmount<<23;
}
/*
* fastpow(f,n) gives a rather *rough* estimate of a float number f to the
* power of an integer number n (y=f^n). It is fast but result can be quite a
* bit off, since we directly mess with the floating point exponent.
*
* Use it only for getting rough estimates of the values and where precision
* is not that important.
*/
float fast_pow(const float f, const int n)
{
long *lp,l;
lp=(long*)(&f);
l=*lp;l-=0x3F800000l;l<<=(n-1);l+=0x3F800000l;
*lp=l;
return f;
}
float fast_root(const float f, const int n)
{
long *lp,l;
lp=(long*)(&f);
l=*lp;l-=0x3F800000l;l>>=(n-1);l+=0x3F800000l;
*lp=l;
return f;
}
/*
* Code for approximation of cos, sin, tan and inv sin, etc.
* Surprisingly accurate and very usable.
*
* Domain:
* Sin/Cos [0, pi/2]
* Tan [0,pi/4]
* InvSin/Cos [0, 1]
* InvTan [-1, 1]
*/
float fast_sin(const float val)
{
float fASqr = val*val;
float fResult = -2.39e-08f;
fResult *= fASqr;
fResult += 2.7526e-06f;
fResult *= fASqr;
fResult -= 1.98409e-04f;
fResult *= fASqr;
fResult += 8.3333315e-03f;
fResult *= fASqr;
fResult -= 1.666666664e-01f;
fResult *= fASqr;
fResult += 1.0f;
fResult *= val;
return fResult;
}
float fast_cos(const float val)
{
float fASqr = val*val;
float fResult = -2.605e-07f;
fResult *= fASqr;
fResult += 2.47609e-05f;
fResult *= fASqr;
fResult -= 1.3888397e-03f;
fResult *= fASqr;
fResult += 4.16666418e-02f;
fResult *= fASqr;
fResult -= 4.999999963e-01f;
fResult *= fASqr;
fResult += 1.0f;
return fResult;
}
float fast_tan(const float val)
{
float fASqr = val*val;
float fResult = 9.5168091e-03f;
fResult *= fASqr;
fResult += 2.900525e-03f;
fResult *= fASqr;
fResult += 2.45650893e-02f;
fResult *= fASqr;
fResult += 5.33740603e-02f;
fResult *= fASqr;
fResult += 1.333923995e-01f;
fResult *= fASqr;
fResult += 3.333314036e-01f;
fResult *= fASqr;
fResult += 1.0f;
fResult *= val;
return fResult;
}
float fast_asin(float val)
{
float fRoot = sqrt(1.0f-val);
float fResult = -0.0187293f;
fResult *= val;
fResult += 0.0742610f;
fResult *= val;
fResult -= 0.2121144f;
fResult *= val;
fResult += 1.5707288f;
fResult = SGD_PI_2 - fRoot*fResult;
return fResult;
}
float fast_acos(float val)
{
float fRoot = sqrt(1.0f-val);
float fResult = -0.0187293f;
fResult *= val;
fResult += 0.0742610f;
fResult *= val;
fResult -= 0.2121144f;
fResult *= val;
fResult += 1.5707288f;
fResult *= fRoot;
return fResult;
}
float fast_atan(float val)
{
float fVSqr = val*val;
float fResult = 0.0028662257f;
fResult *= fVSqr;
fResult -= 0.0161657367f;
fResult *= fVSqr;
fResult += 0.0429096138f;
fResult *= fVSqr;
fResult -= 0.0752896400f;
fResult *= fVSqr;
fResult += 0.1065626393f;
fResult *= fVSqr;
fResult -= 0.1420889944f;
fResult *= fVSqr;
fResult += 0.1999355085f;
fResult *= fVSqr;
fResult -= 0.3333314528f;
fResult *= fVSqr;
fResult += 1.0f;
fResult *= val;
return fResult;
}

View File

@@ -1,117 +0,0 @@
/*
* \file fastmath.hxx
* fast mathematics routines.
*
* Refferences:
*
* A Fast, Compact Approximation of the Exponential Function
* Nicol N. Schraudolph
* IDSIA, Lugano, Switzerland
* http://www.inf.ethz.ch/~schraudo/pubs/exp.pdf
*
* Fast log() Function, by Laurent de Soras:
* http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-Fastlogfunction&forum=totd&id=-1
*
*/
/*
* $Id$
*/
#ifndef _SG_FMATH_HXX
#define _SG_FMATH_HXX 1
#ifndef __cplusplus
# error This library requires C++
#endif
#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif
#include <math.h>
double fast_exp(double val);
double fast_exp2(const double val);
float fast_pow(const float val1, const float val2);
float fast_log2(const float cal);
float fast_root(const float f, const int n);
float _fast_pow2(const float cal);
float _fast_log2(const float val);
float fast_sin(const float val);
float fast_cos(const float val);
float fast_tan(const float val);
float fast_asin(const float val);
float fast_acos(const float val);
float fast_atan(const float val);
void fast_BSL(float &x, register unsigned long shiftAmount);
void fast_BSR(float &x, register unsigned long shiftAmount);
inline float fast_log2 (float val)
{
int * const exp_ptr = reinterpret_cast <int *> (&val);
int x = *exp_ptr;
const int log_2 = ((x >> 23) & 255) - 128;
x &= ~(255 << 23);
x += 127 << 23;
*exp_ptr = x;
val = ((-1.0f/3) * val + 2) * val - 2.0f/3; // (1)
return (val + log_2);
}
/**
* This function is about 3 times faster than the system log() function
* and has an error of about 0.01%
*/
inline float fast_log (const float &val)
{
return (fast_log2 (val) * 0.69314718f);
}
inline float fast_log10 (const float &val)
{
return (fast_log2(val) / 3.321928095f);
}
/**
* This function is about twice as fast as the system pow(x,y) function
*/
inline float fast_pow(const float val1, const float val2)
{
return _fast_pow2(val2 * _fast_log2(val1));
}
/*
* Haven't seen this elsewhere, probably because it is too obvious?
* Anyway, these functions are intended for 32-bit floating point numbers
* only and should work a bit faster than the regular ones.
*/
inline float fast_abs(float f)
{
int i=((*(int*)&f)&0x7fffffff);
return (*(float*)&i);
}
inline float fast_neg(float f)
{
int i=((*(int*)&f)^0x80000000);
return (*(float*)&i);
}
inline int fast_sgn(float f)
{
return 1+(((*(int*)&f)>>31)<<1);
}
#endif // !_SG_FMATH_HXX

View File

@@ -16,22 +16,20 @@
// 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 Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
// 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.
//
// $Id$
#include <simgear/compiler.h>
#include <stdlib.h> // for exit()
#include STL_STRING
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/props/props.hxx>
#include "interpolater.hxx"
@@ -39,22 +37,29 @@ SG_USING_STD(string);
// Constructor -- starts with an empty table.
SGInterpTable::SGInterpTable()
: size(0)
{
}
SGInterpTable::SGInterpTable(const SGPropertyNode* interpolation)
{
if (!interpolation)
return;
std::vector<SGPropertyNode_ptr> entries = interpolation->getChildren("entry");
for (unsigned i = 0; i < entries.size(); ++i)
addEntry(entries[i]->getDoubleValue("ind", 0.0),
entries[i]->getDoubleValue("dep", 0.0));
}
// Constructor -- loads the interpolation table from the specified
// file
SGInterpTable::SGInterpTable( const string& file )
: size(0)
{
SG_LOG( SG_MATH, SG_INFO, "Initializing Interpolator for " << file );
sg_gzifstream in( file );
if ( !in.is_open() ) {
SG_LOG( SG_GENERAL, SG_ALERT, "Cannot open file: " << file );
exit(-1);
return;
}
in >> skipcomment;
@@ -62,8 +67,7 @@ SGInterpTable::SGInterpTable( const string& file )
double ind, dep;
in >> ind >> dep;
in >> skipws;
table.push_back(Entry(ind, dep));
size++;
_table[ind] = dep;
}
}
@@ -71,51 +75,42 @@ SGInterpTable::SGInterpTable( const string& file )
// Add an entry to the table.
void SGInterpTable::addEntry (double ind, double dep)
{
table.push_back(Entry(ind,dep));
size++;
_table[ind] = dep;
}
// Given an x value, linearly interpolate the y value from the table
double SGInterpTable::interpolate(double x) const
{
int i;
double y;
if (size == 0.0) {
return 0.0;
}
i = 0;
while ( (i < size) && (x > table[i].ind) ) {
// cout << " i = " << i << " table[i].ind = " << table[i].ind << endl;
// cout << " size = " << size << endl;
i++;
}
// printf ("i = %d ", i);
if ( i <= 0 ) {
SG_LOG( SG_MATH, SG_DEBUG,
"interpolate(): lookup error, x to small = " << x );
return table[0].dep;
}
// cout << " table[size-1].ind = " << table[size-1].ind << endl;
if ( i >= size ) {
SG_LOG( SG_MATH, SG_DEBUG,
"interpolate(): lookup error, x to big = " << x );
return table[size-1].dep;
}
// y = y1 + (y0 - y1)(x - x1) / (x0 - x1)
y = table[i].dep +
( (table[i-1].dep - table[i].dep) *
(x - table[i].ind) ) /
(table[i-1].ind - table[i].ind);
return(y);
// Empty table??
if (_table.empty())
return 0;
// Find the table bounds for the requested input.
Table::const_iterator upBoundIt = _table.upper_bound(x);
// points to a value outside the map. That is we are out of range.
// use the last entry
if (upBoundIt == _table.end())
return _table.rbegin()->second;
// points to the first key must be lower
// use the first entry
if (upBoundIt == _table.begin())
return upBoundIt->second;
// we know that we do not stand at the beginning, so it is safe to do so
Table::const_iterator loBoundIt = upBoundIt;
--loBoundIt;
// Just do linear interpolation.
double loBound = loBoundIt->first;
double upBound = upBoundIt->first;
double loVal = loBoundIt->second;
double upVal = upBoundIt->second;
// division by zero should not happen since the std::map
// has sorted out duplicate entries before. Also since we have a
// map, we know that we get different first values for different iterators
return loVal + (upVal - loVal)*(x - loBound)/(upBound - loBound);
}

Some files were not shown because too many files have changed in this diff Show More