[pkg-fgfs-crew] r196 - in /simgear/trunk: ./ CMakeModules/ debian/ projects/VC90/ simgear/ simgear/bucket/ simgear/compatibility/ simgear/compatibility/MIPSpro721/ simgear/compatibility/MIPSpro740/ simgear/debug/ simgear/environment/ simgear/ephemeris/ simgear/hla/ simgear/io/ simgear/magvar/ simgear/math/ simgear/misc/ simgear/nasal/ simgear/props/ simgear/route/ simgear/scene/ simgear/scene/bvh/ simgear/scene/material/ simgear/scene/model/ simgear/scene/sky/ simgear/scene/tgdb/ simgear/scene/tsync/ simgear/scene/util/ simgear/screen/ simgear/serial/ simgear/sound/ simgear/structure/ simgear/threads/ simgear/timing/ simgear/xml/

ovek at users.alioth.debian.org ovek at users.alioth.debian.org
Sun Jul 15 09:07:06 UTC 2012


Author: ovek
Date: Sun Jul 15 09:07:01 2012
New Revision: 196

URL: http://svn.debian.org/wsvn/pkg-fgfs/?sc=1&rev=196
Log:
Imported SimGear 2.6.0.

Added:
    simgear/trunk/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/CMakeLists.txt
    simgear/trunk/CMakeModules/
      - copied from r195, simgear/branches/upstream/current/CMakeModules/
    simgear/trunk/Doxyfile
      - copied unchanged from r195, simgear/branches/upstream/current/Doxyfile
    simgear/trunk/Thanks
      - copied unchanged from r195, simgear/branches/upstream/current/Thanks
    simgear/trunk/simgear/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/CMakeLists.txt
    simgear/trunk/simgear/bucket/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/bucket/CMakeLists.txt
    simgear/trunk/simgear/debug/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/debug/CMakeLists.txt
    simgear/trunk/simgear/environment/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/environment/CMakeLists.txt
    simgear/trunk/simgear/environment/test_metar.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/environment/test_metar.cxx
    simgear/trunk/simgear/environment/visual_enviro.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/environment/visual_enviro.cxx
    simgear/trunk/simgear/ephemeris/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/ephemeris/CMakeLists.txt
    simgear/trunk/simgear/hla/HLADataElementVisitor.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/hla/HLADataElementVisitor.hxx
    simgear/trunk/simgear/hla/HLADataTypeVisitor.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/hla/HLADataTypeVisitor.cxx
    simgear/trunk/simgear/io/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/io/CMakeLists.txt
    simgear/trunk/simgear/io/HTTPClient.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/io/HTTPClient.cxx
    simgear/trunk/simgear/io/HTTPClient.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/io/HTTPClient.hxx
    simgear/trunk/simgear/io/HTTPRequest.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/io/HTTPRequest.cxx
    simgear/trunk/simgear/io/HTTPRequest.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/io/HTTPRequest.hxx
    simgear/trunk/simgear/io/httpget.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/io/httpget.cxx
    simgear/trunk/simgear/io/test_HTTP.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/io/test_HTTP.cxx
    simgear/trunk/simgear/io/test_binobj.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/io/test_binobj.cxx
    simgear/trunk/simgear/magvar/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/magvar/CMakeLists.txt
    simgear/trunk/simgear/math/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/math/CMakeLists.txt
    simgear/trunk/simgear/misc/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/misc/CMakeLists.txt
    simgear/trunk/simgear/misc/path_test.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/misc/path_test.cxx
    simgear/trunk/simgear/misc/strutils_test.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/misc/strutils_test.cxx
    simgear/trunk/simgear/misc/swap_test.cpp
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/misc/swap_test.cpp
    simgear/trunk/simgear/misc/tabbed_values_test.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/misc/tabbed_values_test.cxx
    simgear/trunk/simgear/nasal/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/nasal/CMakeLists.txt
    simgear/trunk/simgear/props/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/props/CMakeLists.txt
    simgear/trunk/simgear/props/propsfwd.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/props/propsfwd.hxx
    simgear/trunk/simgear/route/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/route/CMakeLists.txt
    simgear/trunk/simgear/scene/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/CMakeLists.txt
    simgear/trunk/simgear/scene/bvh/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/bvh/CMakeLists.txt
    simgear/trunk/simgear/scene/material/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/material/CMakeLists.txt
    simgear/trunk/simgear/scene/material/EffectData.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/material/EffectData.cxx
    simgear/trunk/simgear/scene/material/EffectData.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/material/EffectData.hxx
    simgear/trunk/simgear/scene/material/EffectElement.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/material/EffectElement.hxx
    simgear/trunk/simgear/scene/material/EffectElementBuilder.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/material/EffectElementBuilder.hxx
    simgear/trunk/simgear/scene/material/ElementBuilder.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/material/ElementBuilder.cxx
    simgear/trunk/simgear/scene/material/ElementBuilder.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/material/ElementBuilder.hxx
    simgear/trunk/simgear/scene/model/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/model/CMakeLists.txt
    simgear/trunk/simgear/scene/model/shadowvolume.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/model/shadowvolume.cxx
    simgear/trunk/simgear/scene/model/shadowvolume.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/model/shadowvolume.hxx
    simgear/trunk/simgear/scene/sky/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/sky/CMakeLists.txt
    simgear/trunk/simgear/scene/tgdb/BucketBox.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/tgdb/BucketBox.hxx
    simgear/trunk/simgear/scene/tgdb/BucketBoxTest.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/tgdb/BucketBoxTest.cxx
    simgear/trunk/simgear/scene/tgdb/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/tgdb/CMakeLists.txt
    simgear/trunk/simgear/scene/tgdb/ReaderWriterSPT.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/tgdb/ReaderWriterSPT.cxx
    simgear/trunk/simgear/scene/tgdb/ReaderWriterSPT.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/tgdb/ReaderWriterSPT.hxx
    simgear/trunk/simgear/scene/tsync/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/tsync/CMakeLists.txt
    simgear/trunk/simgear/scene/util/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/util/CMakeLists.txt
    simgear/trunk/simgear/scene/util/PathOptions.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/util/PathOptions.cxx
    simgear/trunk/simgear/scene/util/PathOptions.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/util/PathOptions.hxx
    simgear/trunk/simgear/scene/util/SGCoreOSGDependant.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/util/SGCoreOSGDependant.cxx
    simgear/trunk/simgear/scene/util/SGReaderWriterOptions.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/util/SGReaderWriterOptions.hxx
    simgear/trunk/simgear/scene/util/project.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/util/project.cxx
    simgear/trunk/simgear/scene/util/project.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/scene/util/project.hxx
    simgear/trunk/simgear/screen/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/screen/CMakeLists.txt
    simgear/trunk/simgear/serial/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/serial/CMakeLists.txt
    simgear/trunk/simgear/simgear_config.h-msvc90
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/simgear_config.h-msvc90
    simgear/trunk/simgear/simgear_config_cmake.h.in
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/simgear_config_cmake.h.in
    simgear/trunk/simgear/sound/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/sound/CMakeLists.txt
    simgear/trunk/simgear/structure/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/structure/CMakeLists.txt
    simgear/trunk/simgear/structure/SGPerfMon.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/structure/SGPerfMon.cxx
    simgear/trunk/simgear/structure/SGPerfMon.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/structure/SGPerfMon.hxx
    simgear/trunk/simgear/structure/intern.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/structure/intern.cxx
    simgear/trunk/simgear/structure/singleton.hpp
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/structure/singleton.hpp
    simgear/trunk/simgear/threads/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/threads/CMakeLists.txt
    simgear/trunk/simgear/timing/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/timing/CMakeLists.txt
    simgear/trunk/simgear/timing/testtimestamp.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/timing/testtimestamp.cxx
    simgear/trunk/simgear/xml/CMakeLists.txt
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/xml/CMakeLists.txt
    simgear/trunk/simgear/xml/XMLStaticParser.hxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/xml/XMLStaticParser.hxx
    simgear/trunk/simgear/xml/sample.xml
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/xml/sample.xml
    simgear/trunk/simgear/xml/testEasyXML.cxx
      - copied unchanged from r195, simgear/branches/upstream/current/simgear/xml/testEasyXML.cxx
Removed:
    simgear/trunk/INSTALL
    simgear/trunk/Makefile.am
    simgear/trunk/Makefile.in
    simgear/trunk/acinclude.m4
    simgear/trunk/aclocal.m4
    simgear/trunk/autogen.sh
    simgear/trunk/config.guess
    simgear/trunk/config.sub
    simgear/trunk/configure
    simgear/trunk/configure.ac
    simgear/trunk/depcomp
    simgear/trunk/install-sh
    simgear/trunk/missing
    simgear/trunk/projects/VC90/.gitignore
    simgear/trunk/simgear/Makefile.am
    simgear/trunk/simgear/Makefile.in
    simgear/trunk/simgear/bucket/Makefile.am
    simgear/trunk/simgear/bucket/Makefile.in
    simgear/trunk/simgear/compatibility/MIPSpro721/Makefile.am
    simgear/trunk/simgear/compatibility/MIPSpro721/Makefile.in
    simgear/trunk/simgear/compatibility/MIPSpro740/Makefile.am
    simgear/trunk/simgear/compatibility/MIPSpro740/Makefile.in
    simgear/trunk/simgear/compatibility/Makefile.am
    simgear/trunk/simgear/compatibility/Makefile.in
    simgear/trunk/simgear/debug/Makefile.am
    simgear/trunk/simgear/debug/Makefile.in
    simgear/trunk/simgear/environment/Makefile.am
    simgear/trunk/simgear/environment/Makefile.in
    simgear/trunk/simgear/ephemeris/Makefile.am
    simgear/trunk/simgear/ephemeris/Makefile.in
    simgear/trunk/simgear/hla/HLA13Federate.cxx
    simgear/trunk/simgear/hla/HLA13Federate.hxx
    simgear/trunk/simgear/hla/Makefile.am
    simgear/trunk/simgear/hla/Makefile.in
    simgear/trunk/simgear/io/Makefile.am
    simgear/trunk/simgear/io/Makefile.in
    simgear/trunk/simgear/magvar/Makefile.am
    simgear/trunk/simgear/magvar/Makefile.in
    simgear/trunk/simgear/math/Makefile.am
    simgear/trunk/simgear/math/Makefile.in
    simgear/trunk/simgear/math/project.cxx
    simgear/trunk/simgear/math/project.hxx
    simgear/trunk/simgear/misc/Makefile.am
    simgear/trunk/simgear/misc/Makefile.in
    simgear/trunk/simgear/misc/PathOptions.cxx
    simgear/trunk/simgear/misc/PathOptions.hxx
    simgear/trunk/simgear/misc/sg_sleep.cxx
    simgear/trunk/simgear/misc/sg_sleep.hxx
    simgear/trunk/simgear/nasal/Makefile.am
    simgear/trunk/simgear/nasal/Makefile.in
    simgear/trunk/simgear/props/Makefile.am
    simgear/trunk/simgear/props/Makefile.in
    simgear/trunk/simgear/route/Makefile.am
    simgear/trunk/simgear/route/Makefile.in
    simgear/trunk/simgear/scene/Makefile.am
    simgear/trunk/simgear/scene/Makefile.in
    simgear/trunk/simgear/scene/bvh/Makefile.am
    simgear/trunk/simgear/scene/bvh/Makefile.in
    simgear/trunk/simgear/scene/material/Makefile.am
    simgear/trunk/simgear/scene/material/Makefile.in
    simgear/trunk/simgear/scene/model/Makefile.am
    simgear/trunk/simgear/scene/model/Makefile.in
    simgear/trunk/simgear/scene/model/SGPagedLOD.cxx
    simgear/trunk/simgear/scene/model/SGPagedLOD.hxx
    simgear/trunk/simgear/scene/model/SGReaderWriterXMLOptions.hxx
    simgear/trunk/simgear/scene/sky/Makefile.am
    simgear/trunk/simgear/scene/sky/Makefile.in
    simgear/trunk/simgear/scene/tgdb/Makefile.am
    simgear/trunk/simgear/scene/tgdb/Makefile.in
    simgear/trunk/simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx
    simgear/trunk/simgear/scene/tsync/Makefile.am
    simgear/trunk/simgear/scene/tsync/Makefile.in
    simgear/trunk/simgear/scene/util/Makefile.am
    simgear/trunk/simgear/scene/util/Makefile.in
    simgear/trunk/simgear/screen/Makefile.am
    simgear/trunk/simgear/screen/Makefile.in
    simgear/trunk/simgear/serial/Makefile.am
    simgear/trunk/simgear/serial/Makefile.in
    simgear/trunk/simgear/simgear_config.h-msvc71
    simgear/trunk/simgear/simgear_config.h.in
    simgear/trunk/simgear/simgear_config.h.vc5
    simgear/trunk/simgear/sound/Makefile.am
    simgear/trunk/simgear/sound/Makefile.in
    simgear/trunk/simgear/structure/Makefile.am
    simgear/trunk/simgear/structure/Makefile.in
    simgear/trunk/simgear/threads/Makefile.am
    simgear/trunk/simgear/threads/Makefile.in
    simgear/trunk/simgear/timing/Makefile.am
    simgear/trunk/simgear/timing/Makefile.in
    simgear/trunk/simgear/xml/Makefile.am
    simgear/trunk/simgear/xml/Makefile.in
Modified:
    simgear/trunk/README.OSG
    simgear/trunk/debian/changelog
    simgear/trunk/projects/VC90/SimGear.vcproj
    simgear/trunk/simgear/debug/debug_types.h
    simgear/trunk/simgear/environment/metar.cxx
    simgear/trunk/simgear/environment/metar.hxx
    simgear/trunk/simgear/hla/CMakeLists.txt
    simgear/trunk/simgear/hla/HLAArrayDataElement.cxx
    simgear/trunk/simgear/hla/HLAArrayDataElement.hxx
    simgear/trunk/simgear/hla/HLAArrayDataType.cxx
    simgear/trunk/simgear/hla/HLAArrayDataType.hxx
    simgear/trunk/simgear/hla/HLABasicDataElement.cxx
    simgear/trunk/simgear/hla/HLABasicDataElement.hxx
    simgear/trunk/simgear/hla/HLADataElement.cxx
    simgear/trunk/simgear/hla/HLADataElement.hxx
    simgear/trunk/simgear/hla/HLADataTypeVisitor.hxx
    simgear/trunk/simgear/hla/HLAEnumeratedDataElement.cxx
    simgear/trunk/simgear/hla/HLAEnumeratedDataElement.hxx
    simgear/trunk/simgear/hla/HLAFederate.cxx
    simgear/trunk/simgear/hla/HLAFederate.hxx
    simgear/trunk/simgear/hla/HLAFixedRecordDataElement.cxx
    simgear/trunk/simgear/hla/HLAFixedRecordDataElement.hxx
    simgear/trunk/simgear/hla/HLAInteractionClass.hxx
    simgear/trunk/simgear/hla/HLAOMTXmlVisitor.cxx
    simgear/trunk/simgear/hla/HLAObjectClass.hxx
    simgear/trunk/simgear/hla/HLAObjectInstance.cxx
    simgear/trunk/simgear/hla/HLAObjectInstance.hxx
    simgear/trunk/simgear/hla/HLAPropertyDataElement.cxx
    simgear/trunk/simgear/hla/HLAPropertyDataElement.hxx
    simgear/trunk/simgear/hla/HLAVariantDataElement.cxx
    simgear/trunk/simgear/hla/HLAVariantDataElement.hxx
    simgear/trunk/simgear/hla/RTI13Ambassador.hxx
    simgear/trunk/simgear/hla/RTI13Federate.cxx
    simgear/trunk/simgear/hla/RTI13Federate.hxx
    simgear/trunk/simgear/hla/RTI13ObjectClass.cxx
    simgear/trunk/simgear/hla/RTI13ObjectClass.hxx
    simgear/trunk/simgear/hla/RTI13ObjectInstance.cxx
    simgear/trunk/simgear/hla/RTI13ObjectInstance.hxx
    simgear/trunk/simgear/hla/RTIData.hxx
    simgear/trunk/simgear/hla/RTIFederate.hxx
    simgear/trunk/simgear/hla/RTIObjectClass.cxx
    simgear/trunk/simgear/hla/RTIObjectInstance.hxx
    simgear/trunk/simgear/io/decode_binobj.cxx
    simgear/trunk/simgear/io/iochannel.cxx
    simgear/trunk/simgear/io/iochannel.hxx
    simgear/trunk/simgear/io/raw_socket.cxx
    simgear/trunk/simgear/io/raw_socket.hxx
    simgear/trunk/simgear/io/sg_binobj.cxx
    simgear/trunk/simgear/io/sg_binobj.hxx
    simgear/trunk/simgear/io/sg_file.cxx
    simgear/trunk/simgear/io/sg_file.hxx
    simgear/trunk/simgear/io/sg_netChannel.cxx
    simgear/trunk/simgear/io/sg_netChannel.hxx
    simgear/trunk/simgear/io/sg_netChat.cxx
    simgear/trunk/simgear/io/sg_netChat.hxx
    simgear/trunk/simgear/io/sg_socket.cxx
    simgear/trunk/simgear/io/sg_socket_udp.cxx
    simgear/trunk/simgear/io/sg_socket_udp.hxx
    simgear/trunk/simgear/magvar/testmagvar.cxx
    simgear/trunk/simgear/math/SGBox.hxx
    simgear/trunk/simgear/math/SGGeod.cxx
    simgear/trunk/simgear/math/SGMathTest.cxx
    simgear/trunk/simgear/math/SGQuat.hxx
    simgear/trunk/simgear/math/SGSphere.hxx
    simgear/trunk/simgear/math/SGVec3.hxx
    simgear/trunk/simgear/math/sg_random.h
    simgear/trunk/simgear/misc/interpolator.cxx
    simgear/trunk/simgear/misc/sg_dir.cxx
    simgear/trunk/simgear/misc/sg_dir.hxx
    simgear/trunk/simgear/misc/sg_path.cxx
    simgear/trunk/simgear/misc/sg_path.hxx
    simgear/trunk/simgear/misc/strutils.cxx
    simgear/trunk/simgear/misc/strutils.hxx
    simgear/trunk/simgear/misc/texcoord.cxx
    simgear/trunk/simgear/misc/zfstream.cxx
    simgear/trunk/simgear/misc/zfstream.hxx
    simgear/trunk/simgear/nasal/code.c
    simgear/trunk/simgear/nasal/codegen.c
    simgear/trunk/simgear/nasal/iolib.c
    simgear/trunk/simgear/nasal/lib.c
    simgear/trunk/simgear/nasal/nasal.h
    simgear/trunk/simgear/nasal/vector.c
    simgear/trunk/simgear/props/condition.cxx
    simgear/trunk/simgear/props/condition.hxx
    simgear/trunk/simgear/props/propertyObject.cxx
    simgear/trunk/simgear/props/propertyObject.hxx
    simgear/trunk/simgear/props/propertyObject_test.cxx
    simgear/trunk/simgear/props/props.cxx
    simgear/trunk/simgear/props/props.hxx
    simgear/trunk/simgear/props/props_io.cxx
    simgear/trunk/simgear/props/props_io.hxx
    simgear/trunk/simgear/props/props_test.cxx
    simgear/trunk/simgear/props/tiedpropertylist.hxx
    simgear/trunk/simgear/scene/material/Effect.cxx
    simgear/trunk/simgear/scene/material/Effect.hxx
    simgear/trunk/simgear/scene/material/EffectBuilder.cxx
    simgear/trunk/simgear/scene/material/EffectBuilder.hxx
    simgear/trunk/simgear/scene/material/EffectCullVisitor.cxx
    simgear/trunk/simgear/scene/material/Technique.cxx
    simgear/trunk/simgear/scene/material/Technique.hxx
    simgear/trunk/simgear/scene/material/TextureBuilder.cxx
    simgear/trunk/simgear/scene/material/TextureBuilder.hxx
    simgear/trunk/simgear/scene/material/makeEffect.cxx
    simgear/trunk/simgear/scene/material/mat.cxx
    simgear/trunk/simgear/scene/material/mat.hxx
    simgear/trunk/simgear/scene/material/mipmap.cxx
    simgear/trunk/simgear/scene/material/mipmap.hxx
    simgear/trunk/simgear/scene/model/CheckSceneryVisitor.cxx
    simgear/trunk/simgear/scene/model/CheckSceneryVisitor.hxx
    simgear/trunk/simgear/scene/model/ModelRegistry.cxx
    simgear/trunk/simgear/scene/model/SGReaderWriterXML.cxx
    simgear/trunk/simgear/scene/model/model.cxx
    simgear/trunk/simgear/scene/model/model.hxx
    simgear/trunk/simgear/scene/model/modellib.cxx
    simgear/trunk/simgear/scene/model/modellib.hxx
    simgear/trunk/simgear/scene/model/placement.cxx
    simgear/trunk/simgear/scene/sky/CloudShaderGeometry.cxx
    simgear/trunk/simgear/scene/sky/CloudShaderGeometry.hxx
    simgear/trunk/simgear/scene/sky/cloud.cxx
    simgear/trunk/simgear/scene/sky/cloud.hxx
    simgear/trunk/simgear/scene/sky/cloudfield.cxx
    simgear/trunk/simgear/scene/sky/cloudfield.hxx
    simgear/trunk/simgear/scene/sky/dome.cxx
    simgear/trunk/simgear/scene/sky/moon.cxx
    simgear/trunk/simgear/scene/sky/newcloud.cxx
    simgear/trunk/simgear/scene/sky/newcloud.hxx
    simgear/trunk/simgear/scene/sky/oursun.cxx
    simgear/trunk/simgear/scene/sky/sky.cxx
    simgear/trunk/simgear/scene/sky/sky.hxx
    simgear/trunk/simgear/scene/tgdb/SGOceanTile.cxx
    simgear/trunk/simgear/scene/tgdb/SGOceanTile.hxx
    simgear/trunk/simgear/scene/tgdb/SGReaderWriterBTG.cxx
    simgear/trunk/simgear/scene/tgdb/TileEntry.cxx
    simgear/trunk/simgear/scene/tgdb/TreeBin.cxx
    simgear/trunk/simgear/scene/tgdb/TreeBin.hxx
    simgear/trunk/simgear/scene/tgdb/apt_signs.cxx
    simgear/trunk/simgear/scene/tgdb/obj.cxx
    simgear/trunk/simgear/scene/tgdb/obj.hxx
    simgear/trunk/simgear/scene/tgdb/pt_lights.cxx
    simgear/trunk/simgear/scene/tsync/terrasync.cxx
    simgear/trunk/simgear/scene/tsync/terrasync.hxx
    simgear/trunk/simgear/scene/util/SGSceneUserData.hxx
    simgear/trunk/simgear/scene/util/StateAttributeFactory.cxx
    simgear/trunk/simgear/scene/util/StateAttributeFactory.hxx
    simgear/trunk/simgear/screen/screen-dump.cxx
    simgear/trunk/simgear/screen/tr.cxx
    simgear/trunk/simgear/sg_inlines.h
    simgear/trunk/simgear/sound/openal_test1.cxx
    simgear/trunk/simgear/sound/sample_group.cxx
    simgear/trunk/simgear/sound/sample_group.hxx
    simgear/trunk/simgear/sound/sample_openal.cxx
    simgear/trunk/simgear/sound/sample_openal.hxx
    simgear/trunk/simgear/sound/soundmgr_openal.cxx
    simgear/trunk/simgear/sound/soundmgr_openal.hxx
    simgear/trunk/simgear/sound/xmlsound.cxx
    simgear/trunk/simgear/sound/xmlsound.hxx
    simgear/trunk/simgear/structure/SGAtomic.cxx
    simgear/trunk/simgear/structure/SGAtomic.hxx
    simgear/trunk/simgear/structure/SGExpression.hxx
    simgear/trunk/simgear/structure/SGSmplhist.cxx
    simgear/trunk/simgear/structure/SGSmplhist.hxx
    simgear/trunk/simgear/structure/SGSmplstat.cxx
    simgear/trunk/simgear/structure/SGSmplstat.hxx
    simgear/trunk/simgear/structure/Singleton.hxx
    simgear/trunk/simgear/structure/StringTable.cxx
    simgear/trunk/simgear/structure/StringTable.hxx
    simgear/trunk/simgear/structure/commands.cxx
    simgear/trunk/simgear/structure/commands.hxx
    simgear/trunk/simgear/structure/event_mgr.cxx
    simgear/trunk/simgear/structure/subsystem_mgr.cxx
    simgear/trunk/simgear/structure/subsystem_mgr.hxx
    simgear/trunk/simgear/threads/SGQueue.hxx
    simgear/trunk/simgear/threads/SGThread.cxx
    simgear/trunk/simgear/threads/SGThread.hxx
    simgear/trunk/simgear/timing/timestamp.cxx
    simgear/trunk/simgear/timing/timestamp.hxx
    simgear/trunk/simgear/timing/timezone.cxx
    simgear/trunk/version

Modified: simgear/trunk/README.OSG
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/README.OSG?rev=196&op=diff
==============================================================================
--- simgear/trunk/README.OSG (original)
+++ simgear/trunk/README.OSG Sun Jul 15 09:07:01 2012
@@ -1,10 +1,9 @@
 [This file is mirrored in both the FlightGear and SimGear packages.]
 
-You *must* have OpenSceneGraph (OSG) installed to build this version of 
+You *must* have OpenSceneGraph (OSG) installed to build this version of
 FlightGear.
 
-Notice that FlightGear 1.9.0 requires at least version 2.7.8. Using earlier 
-versions of OSG will yield serious rendering bugs. 
+Notice that FlightGear 2.6.0 requires at least version 3.0.0.
 
 You can get the latest version of OSG from:
 
@@ -22,6 +21,6 @@
 [ While running ccmake: press 'c' to configure, press 'c' once more, and
   then press 'g' to generate and exit ]
 
-make 
+make
 sudo make install
 

Modified: simgear/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/debian/changelog?rev=196&op=diff
==============================================================================
--- simgear/trunk/debian/changelog (original)
+++ simgear/trunk/debian/changelog Sun Jul 15 09:07:01 2012
@@ -1,3 +1,9 @@
+simgear (2.6.0-1) UNRELEASED; urgency=low
+
+  * New upstream release
+
+ -- Ove Kaaven <ovek at arcticnet.no>  Sun, 15 Jul 2012 10:37:42 +0200
+
 simgear (2.4.0-1.3) unstable; urgency=low
 
   * Non-maintainer upload.

Modified: simgear/trunk/projects/VC90/SimGear.vcproj
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/projects/VC90/SimGear.vcproj?rev=196&op=diff
==============================================================================
--- simgear/trunk/projects/VC90/SimGear.vcproj (original)
+++ simgear/trunk/projects/VC90/SimGear.vcproj Sun Jul 15 09:07:01 2012
@@ -440,6 +440,22 @@
 			Name="Lib_sgio"
 			>
 			<File
+				RelativePath="..\..\simgear\io\HTTPClient.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\io\HTTPClient.hxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\io\HTTPRequest.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\io\HTTPRequest.hxx"
+				>
+			</File>
+			<File
 				RelativePath="..\..\simgear\io\iochannel.cxx"
 				>
 			</File>
@@ -584,14 +600,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\simgear\math\project.cxx"
-				>
-			</File>
-			<File
-				RelativePath="..\..\simgear\math\project.hxx"
-				>
-			</File>
-			<File
 				RelativePath="..\..\simgear\math\sg_geodesy.hxx"
 				>
 			</File>
@@ -636,14 +644,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\simgear\misc\PathOptions.cxx"
-				>
-			</File>
-			<File
-				RelativePath="..\..\simgear\misc\PathOptions.hxx"
-				>
-			</File>
-			<File
 				RelativePath="..\..\simgear\misc\ResourceManager.cxx"
 				>
 			</File>
@@ -668,14 +668,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\simgear\misc\sg_sleep.cxx"
-				>
-			</File>
-			<File
-				RelativePath="..\..\simgear\misc\sg_sleep.hxx"
-				>
-			</File>
-			<File
 				RelativePath="..\..\simgear\misc\sgstream.cxx"
 				>
 			</File>
@@ -1016,25 +1008,25 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\simgear\props\props.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\props\props.hxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\props\props_io.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\props\props_io.hxx"
+				>
+			</File>
+			<File
 				RelativePath="..\..\simgear\props\tiedpropertylist.hxx"
 				>
 			</File>
-			<File
-				RelativePath="..\..\simgear\props\props.cxx"
-				>
-			</File>
-			<File
-				RelativePath="..\..\simgear\props\props.hxx"
-				>
-			</File>
-			<File
-				RelativePath="..\..\simgear\props\props_io.cxx"
-				>
-			</File>
-			<File
-				RelativePath="..\..\simgear\props\props_io.hxx"
-				>
-			</File>
 		</Filter>
 		<Filter
 			Name="Lib_sgmodel"
@@ -1144,14 +1136,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\simgear\scene\model\SGPagedLOD.cxx"
-				>
-			</File>
-			<File
-				RelativePath="..\..\simgear\scene\model\SGPagedLOD.hxx"
-				>
-			</File>
-			<File
 				RelativePath="..\..\simgear\scene\model\SGReaderWriterXML.cxx"
 				>
 			</File>
@@ -1160,10 +1144,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\simgear\scene\model\SGReaderWriterXMLOptions.hxx"
-				>
-			</File>
-			<File
 				RelativePath="..\..\simgear\scene\model\SGRotateTransform.cxx"
 				>
 			</File>
@@ -1360,6 +1340,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\simgear\scene\tgdb\BucketBox.hxx"
+				>
+			</File>
+			<File
 				RelativePath="..\..\simgear\scene\tgdb\GroundLightManager.cxx"
 				>
 			</File>
@@ -1384,6 +1368,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\simgear\scene\tgdb\ReaderWriterSPT.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\scene\tgdb\ReaderWriterSPT.hxx"
+				>
+			</File>
+			<File
 				RelativePath="..\..\simgear\scene\tgdb\ReaderWriterSTG.cxx"
 				>
 			</File>
@@ -1408,10 +1400,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\simgear\scene\tgdb\SGReaderWriterBTGOptions.hxx"
-				>
-			</File>
-			<File
 				RelativePath="..\..\simgear\scene\tgdb\SGVasiDrawable.cxx"
 				>
 			</File>
@@ -1459,7 +1447,7 @@
 				RelativePath="..\..\simgear\scene\tgdb\userdata.hxx"
 				>
 			</File>
-		</Filter>
+		</Filter>
 		<Filter
 			Name="Lib_sgtsync"
 			>
@@ -1481,6 +1469,14 @@
 			</File>
 			<File
 				RelativePath="..\..\simgear\threads\SGQueue.hxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\threads\SGThread.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\threads\SGThread.hxx"
 				>
 			</File>
 		</Filter>
@@ -1552,6 +1548,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\simgear\structure\SGAtomic.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\structure\SGAtomic.hxx"
+				>
+			</File>
+			<File
 				RelativePath="..\..\simgear\structure\SGBinding.cxx"
 				>
 			</File>
@@ -1568,6 +1572,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\simgear\structure\SGPerfMon.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\structure\SGPerfMon.hxx"
+				>
+			</File>
+			<File
 				RelativePath="..\..\simgear\structure\SGReferenced.hxx"
 				>
 			</File>
@@ -1589,6 +1601,10 @@
 			</File>
 			<File
 				RelativePath="..\..\simgear\structure\SGSmplstat.hxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\structure\Singleton.hxx"
 				>
 			</File>
 			<File
@@ -1778,11 +1794,27 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\simgear\scene\util\PathOptions.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\scene\util\PathOptions.hxx"
+				>
+			</File>
+			<File
 				RelativePath="..\..\simgear\scene\util\PrimitiveUtils.cxx"
 				>
 			</File>
 			<File
 				RelativePath="..\..\simgear\scene\util\PrimitiveUtils.hxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\scene\util\project.cxx"
+				>
+			</File>
+			<File
+				RelativePath="..\..\simgear\scene\util\project.hxx"
 				>
 			</File>
 			<File

Modified: simgear/trunk/simgear/debug/debug_types.h
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/debug/debug_types.h?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/debug/debug_types.h (original)
+++ simgear/trunk/simgear/debug/debug_types.h Sun Jul 15 09:07:01 2012
@@ -1,35 +1,38 @@
 /** \file debug_types.h
- *  Define the various logging classes and prioritiess
+ *  Define the various logging classes and priorities
  */
 
 /** 
  * Define the possible classes/categories of logging messages
  */
 typedef enum {
-    SG_NONE      = 0x00000000,
+    SG_NONE        = 0x00000000,
 
-    SG_TERRAIN   = 0x00000001,
-    SG_ASTRO     = 0x00000002,
-    SG_FLIGHT    = 0x00000004,
-    SG_INPUT     = 0x00000008,
-    SG_GL        = 0x00000010,
-    SG_VIEW      = 0x00000020,
-    SG_COCKPIT   = 0x00000040,
-    SG_GENERAL   = 0x00000080,
-    SG_MATH      = 0x00000100,
-    SG_EVENT     = 0x00000200,
-    SG_AIRCRAFT  = 0x00000400,
-    SG_AUTOPILOT = 0x00000800,
-    SG_IO        = 0x00001000,
-    SG_CLIPPER   = 0x00002000,
-    SG_NETWORK   = 0x00004000,
-    SG_ATC       = 0x00008000,
-    SG_NASAL     = 0x00010000,
-    SG_INSTR     = 0x00020000,
-    SG_SYSTEMS   = 0x00040000,
-    SG_UNDEFD    = 0x00080000, // For range checking
+    SG_TERRAIN     = 0x00000001,
+    SG_ASTRO       = 0x00000002,
+    SG_FLIGHT      = 0x00000004,
+    SG_INPUT       = 0x00000008,
+    SG_GL          = 0x00000010,
+    SG_VIEW        = 0x00000020,
+    SG_COCKPIT     = 0x00000040,
+    SG_GENERAL     = 0x00000080,
+    SG_MATH        = 0x00000100,
+    SG_EVENT       = 0x00000200,
+    SG_AIRCRAFT    = 0x00000400,
+    SG_AUTOPILOT   = 0x00000800,
+    SG_IO          = 0x00001000,
+    SG_CLIPPER     = 0x00002000,
+    SG_NETWORK     = 0x00004000,
+    SG_ATC         = 0x00008000,
+    SG_NASAL       = 0x00010000,
+    SG_INSTR       = 0x00020000,
+    SG_SYSTEMS     = 0x00040000,
+    SG_AI          = 0x00080000,
+    SG_ENVIRONMENT = 0x00100000,
+    SG_SOUND       = 0x00200000,
+    SG_UNDEFD      = 0x00400000, // For range checking
 
-    SG_ALL     = 0xFFFFFFFF
+    SG_ALL         = 0xFFFFFFFF
 } sgDebugClass;
 
 

Modified: simgear/trunk/simgear/environment/metar.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/environment/metar.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/environment/metar.cxx (original)
+++ simgear/trunk/simgear/environment/metar.cxx Sun Jul 15 09:07:01 2012
@@ -32,7 +32,6 @@
 #include <time.h>
 #include <cstring>
 
-#include <simgear/io/sg_socket.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/structure/exception.hxx>
 
@@ -40,32 +39,28 @@
 
 #define NaN SGMetarNaN
 
+using std::string;
+using std::map;
+using std::vector;
+
 /**
- * The constructor takes a Metar string, or a four-letter ICAO code. In the
- * latter case the metar string is downloaded from
- * http://weather.noaa.gov/pub/data/observations/metar/stations/.
+ * The constructor takes a Metar string
  * The constructor throws sg_io_exceptions on failure. The "METAR"
  * keyword has no effect (apart from incrementing the group counter
  * @a grpcount) and can be left away. A keyword "SPECI" is
  * likewise accepted.
  *
  * @param m     ICAO station id or metar string
- * @param proxy proxy host (optional; default: "")
- * @param port  proxy port (optional; default: "80")
- * @param auth  proxy authorization information (optional; default: "")
  *
  * @par Examples:
  * @code
  * SGMetar *m = new SGMetar("METAR KSFO 061656Z 19004KT 9SM SCT100 OVC200 08/03 A3013");
  * double t = m->getTemperature_F();
  * delete m;
- *
- * SGMetar n("KSFO", "proxy.provider.foo", "3128", "proxy-password");
- * double d = n.getDewpoint_C();
+
  * @endcode
  */
-SGMetar::SGMetar(const string& m, const string& proxy, const string& port,
-		const string& auth, const time_t time) :
+SGMetar::SGMetar(const string& m) :
 	_grpcount(0),
 	_x_proxy(false),
 	_year(-1),
@@ -87,16 +82,10 @@
 	_snow(false),
 	_cavok(false)
 {
-	if (m.length() == 4 && isalnum(m[0]) && isalnum(m[1]) && isalnum(m[2]) && isalnum(m[3])) {
-		for (int i = 0; i < 4; i++)
-			_icao[i] = toupper(m[i]);
-		_icao[4] = '\0';
-		_data = loadData(_icao, proxy, port, auth, time);
-	} else {
-		_data = new char[m.length() + 2];	// make room for " \0"
-		strcpy(_data, m.c_str());
-		_url = _data;
-	}
+	_data = new char[m.length() + 2];	// make room for " \0"
+	strcpy(_data, m.c_str());
+	_url = _data;
+		
 	normalizeData();
 
 	_m = _data;
@@ -168,85 +157,6 @@
 	_year = now.tm_year + 1900;
 	_month = now.tm_mon + 1;
 }
-
-
-/**
-  * If called with "KSFO" loads data from
-  * @code
-  * http://weather.noaa.gov/pub/data/observations/metar/stations/KSFO.TXT.
-  * @endcode
-  * Throws sg_io_exception on failure. Gives up after waiting longer than 10 seconds.
-  *
-  * @param id four-letter ICAO Metar station code, e.g. "KSFO".
-  * @param proxy proxy host (optional; default: "")
-  * @param port  proxy port (optional; default: "80")
-  * @param auth  proxy authorization information (optional; default: "")
-  * @return pointer to Metar data string, allocated by new char[].
-  * @see rfc2068.txt for proxy spec ("Proxy-Authorization")
-  */
-char *SGMetar::loadData(const char *id, const string& proxy, const string& port,
-		const string& auth, time_t time)
-{
-	const int buflen = 512;
-	char buf[2 * buflen];
-
-	string metar_server = "weather.noaa.gov";
-	string host = proxy.empty() ? metar_server : proxy;
-	string path = "/pub/data/observations/metar/stations/";
-
-	path += string(id) + ".TXT";
-	_url = "http://" + metar_server + path;
-
-	SGSocket *sock = new SGSocket(host, port.empty() ? "80" : port, "tcp");
-	sock->set_timeout(10000);
-	if (!sock->open(SG_IO_OUT)) {
-		delete sock;
-		throw sg_io_exception("cannot connect to ", sg_location(host));
-	}
-
-	string get = "GET ";
-	if (!proxy.empty())
-		get += "http://" + metar_server;
-
-	sprintf(buf, "%ld", time);
-	get += path + " HTTP/1.0\015\012X-Time: " + buf + "\015\012";
-	get += "Host: " + metar_server + "\015\012";
-
-	if (!auth.empty())
-		get += "Proxy-Authorization: " + auth + "\015\012";
-
-	get += "\015\012";
-	sock->writestring(get.c_str());
-
-	int i;
-
-	// skip HTTP header
-	while ((i = sock->readline(buf, buflen))) {
-		if (i <= 2 && isspace(buf[0]) && (!buf[1] || isspace(buf[1])))
-			break;
-		if (!strncmp(buf, "X-MetarProxy: ", 13))
-			_x_proxy = true;
-	}
-	if (i) {
-		i = sock->readline(buf, buflen);
-		if (i)
-			sock->readline(&buf[i], buflen);
-	}
-
-	sock->close();
-	delete sock;
-
-	char *b = buf;
-	scanBoundary(&b);
-	if (*b == '<')
-		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);
-	return metar;
-}
-
 
 /**
   * Replace any number of subsequent spaces by just one space, and add

Modified: simgear/trunk/simgear/environment/metar.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/environment/metar.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/environment/metar.hxx (original)
+++ simgear/trunk/simgear/environment/metar.hxx Sun Jul 15 09:07:01 2012
@@ -29,18 +29,12 @@
 
 #include <simgear/constants.h>
 
-using std::vector;
-using std::map;
-using std::string;
-
-const double SGMetarNaN = -1E20;
-#define NaN SGMetarNaN
-
 struct Token {
 	const char *id;
 	const char *text;
 };
 
+const double SGMetarNaN = -1E20;
 
 class SGMetar;
 
@@ -48,7 +42,7 @@
 	friend class SGMetar;
 public:
 	SGMetarVisibility() :
-		_distance(NaN),
+		_distance(SGMetarNaN),
 		_direction(-1),
 		_modifier(EQUALS),
 		_tendency(NONE) {}
@@ -70,8 +64,8 @@
 	void set(double dist, int dir = -1, int mod = -1, int tend = -1);
 
 	inline double	getVisibility_m()	const { return _distance; }
-	inline double	getVisibility_ft()	const { return _distance == NaN ? NaN : _distance * SG_METER_TO_FEET; }
-	inline double	getVisibility_sm()	const { return _distance == NaN ? NaN : _distance * SG_METER_TO_SM; }
+	inline double	getVisibility_ft()	const { return _distance == SGMetarNaN ? SGMetarNaN : _distance * SG_METER_TO_FEET; }
+	inline double	getVisibility_sm()	const { return _distance == SGMetarNaN ? SGMetarNaN : _distance * SG_METER_TO_SM; }
 	inline int	getDirection()		const { return _direction; }
 	inline int	getModifier()		const { return _modifier; }
 	inline int	getTendency()		const { return _tendency; }
@@ -93,8 +87,8 @@
 		_deposit_string(0),
 		_extent(-1),
 		_extent_string(0),
-		_depth(NaN),
-		_friction(NaN),
+		_depth(SGMetarNaN),
+		_friction(SGMetarNaN),
 		_friction_string(0),
 		_comment(0),
 		_wind_shear(false) {}
@@ -107,7 +101,7 @@
 	inline double			getFriction()		const { return _friction; }
 	inline const char		*getFrictionString()	const { return _friction_string; }
 	inline const char		*getComment()		const { return _comment; }
-	inline const bool		getWindShear()		const { return _wind_shear; }
+	inline       bool		getWindShear()		const { return _wind_shear; }
 	inline const SGMetarVisibility&	getMinVisibility()	const { return _min_visibility; }
 	inline const SGMetarVisibility&	getMaxVisibility()	const { return _max_visibility; }
 
@@ -146,14 +140,14 @@
 	static const char * COVERAGE_BROKEN_STRING;
 	static const char * COVERAGE_OVERCAST_STRING;
 
-	SGMetarCloud() : _coverage(COVERAGE_NIL), _altitude(NaN), _type(0), _type_long(0) {}
+	SGMetarCloud() : _coverage(COVERAGE_NIL), _altitude(SGMetarNaN), _type(0), _type_long(0) {}
 
 	void set(double alt, Coverage cov = COVERAGE_NIL );
 
 	inline Coverage getCoverage() const { return _coverage; }
 	static Coverage getCoverage( const std::string & coverage );
 	inline double getAltitude_m() const { return _altitude; }
-	inline double getAltitude_ft() const { return _altitude == NaN ? NaN : _altitude * SG_METER_TO_FEET; }
+	inline double getAltitude_ft() const { return _altitude == SGMetarNaN ? SGMetarNaN : _altitude * SG_METER_TO_FEET; }
 	inline const char *getTypeString() const { return _type; }
 	inline const char *getTypeLongString() const { return _type_long; }
 
@@ -167,8 +161,7 @@
 
 class SGMetar {
 public:
-	SGMetar(const string& m, const string& proxy = "", const string& port = "",
-			const string &auth = "", const time_t time = 0);
+	SGMetar(const std::string& m);
 	~SGMetar();
 
 	enum ReportType {
@@ -189,13 +182,13 @@
 		Weather() { intensity = NIL; vincinity = false; }
 		Intensity intensity;
 		bool      vincinity;
-		vector<string> descriptions;
-		vector<string> phenomena;
+		std::vector<std::string> descriptions;
+		std::vector<std::string> phenomena;
 	};
 
 	inline const char *getData()		const { return _data; }
 	inline const char *getUnusedData()	const { return _m; }
-	inline const bool getProxy()		const { return _x_proxy; }
+	inline       bool getProxy()		const { return _x_proxy; }
 	inline const char *getId()		const { return _icao; }
 	inline int	getYear()		const { return _year; }
 	inline int	getMonth()		const { return _month; }
@@ -206,14 +199,14 @@
 
 	inline int	getWindDir()		const { return _wind_dir; }
 	inline double	getWindSpeed_mps()	const { return _wind_speed; }
-	inline double	getWindSpeed_kmh()	const { return _wind_speed == NaN ? NaN : _wind_speed * SG_MPS_TO_KMH; }
-	inline double	getWindSpeed_kt()	const { return _wind_speed == NaN ? NaN : _wind_speed * SG_MPS_TO_KT; }
-	inline double	getWindSpeed_mph()	const { return _wind_speed == NaN ? NaN : _wind_speed * SG_MPS_TO_MPH; }
+	inline double	getWindSpeed_kmh()	const { return _wind_speed == SGMetarNaN ? SGMetarNaN : _wind_speed * SG_MPS_TO_KMH; }
+	inline double	getWindSpeed_kt()	const { return _wind_speed == SGMetarNaN ? SGMetarNaN : _wind_speed * SG_MPS_TO_KT; }
+	inline double	getWindSpeed_mph()	const { return _wind_speed == SGMetarNaN ? SGMetarNaN : _wind_speed * SG_MPS_TO_MPH; }
 
 	inline double	getGustSpeed_mps()	const { return _gust_speed; }
-	inline double	getGustSpeed_kmh()	const { return _gust_speed == NaN ? NaN : _gust_speed * SG_MPS_TO_KMH; }
-	inline double	getGustSpeed_kt()	const { return _gust_speed == NaN ? NaN : _gust_speed * SG_MPS_TO_KT; }
-	inline double	getGustSpeed_mph()	const { return _gust_speed == NaN ? NaN : _gust_speed * SG_MPS_TO_MPH; }
+	inline double	getGustSpeed_kmh()	const { return _gust_speed == SGMetarNaN ? SGMetarNaN : _gust_speed * SG_MPS_TO_KMH; }
+	inline double	getGustSpeed_kt()	const { return _gust_speed == SGMetarNaN ? SGMetarNaN : _gust_speed * SG_MPS_TO_KT; }
+	inline double	getGustSpeed_mph()	const { return _gust_speed == SGMetarNaN ? SGMetarNaN : _gust_speed * SG_MPS_TO_MPH; }
 
 	inline int	getWindRangeFrom()	const { return _wind_range_from; }
 	inline int	getWindRangeTo()	const { return _wind_range_to; }
@@ -224,11 +217,11 @@
 	inline const SGMetarVisibility *getDirVisibility()	const { return _dir_visibility; }
 
 	inline double	getTemperature_C()	const { return _temp; }
-	inline double	getTemperature_F()	const { return _temp == NaN ? NaN : 1.8 * _temp + 32; }
+	inline double	getTemperature_F()	const { return _temp == SGMetarNaN ? SGMetarNaN : 1.8 * _temp + 32; }
 	inline double	getDewpoint_C()		const { return _dewp; }
-	inline double	getDewpoint_F()		const { return _dewp == NaN ? NaN : 1.8 * _dewp + 32; }
-	inline double	getPressure_hPa()	const { return _pressure == NaN ? NaN : _pressure / 100; }
-	inline double	getPressure_inHg()	const { return _pressure == NaN ? NaN : _pressure * SG_PA_TO_INHG; }
+	inline double	getDewpoint_F()		const { return _dewp == SGMetarNaN ? SGMetarNaN : 1.8 * _dewp + 32; }
+	inline double	getPressure_hPa()	const { return _pressure == SGMetarNaN ? SGMetarNaN : _pressure / 100; }
+	inline double	getPressure_inHg()	const { return _pressure == SGMetarNaN ? SGMetarNaN : _pressure * SG_PA_TO_INHG; }
 
 	inline int	getRain()		const { return _rain; }
 	inline int	getHail()		const { return _hail; }
@@ -237,13 +230,13 @@
 
 	double		getRelHumidity()	const;
 
-	inline const vector<SGMetarCloud>& getClouds()	const	{ return _clouds; }
-	inline const map<string, SGMetarRunway>& getRunways()	const	{ return _runways; }
-	inline const vector<string>& getWeather()		const	{ return _weather; }
-	inline const vector<struct Weather> getWeather2()	const   { return _weather2; }
+	inline const std::vector<SGMetarCloud>& getClouds()	const	{ return _clouds; }
+	inline const std::map<std::string, SGMetarRunway>& getRunways()	const	{ return _runways; }
+	inline const std::vector<std::string>& getWeather()		const	{ return _weather; }
+	inline const std::vector<struct Weather> getWeather2()	const   { return _weather2; }
 
 protected:
-	string	_url;
+	std::string	_url;
 	int	_grpcount;
 	bool	_x_proxy;
 	char	*_data;
@@ -267,15 +260,15 @@
 	int	_hail;
 	int	_snow;
 	bool	_cavok;
-	vector<struct Weather> _weather2;
+	std::vector<struct Weather> _weather2;
 
 	SGMetarVisibility		_min_visibility;
 	SGMetarVisibility		_max_visibility;
 	SGMetarVisibility		_vert_visibility;
 	SGMetarVisibility		_dir_visibility[8];
-	vector<SGMetarCloud>		_clouds;
-	map<string, SGMetarRunway>	_runways;
-	vector<string>			_weather;
+	std::vector<SGMetarCloud>		_clouds;
+	std::map<std::string, SGMetarRunway>	_runways;
+	std::vector<std::string>			_weather;
 
 	bool	scanPreambleDate();
 	bool	scanPreambleTime();
@@ -303,10 +296,7 @@
 	int	scanNumber(char **str, int *num, int min, int max = 0);
 	bool	scanBoundary(char **str);
 	const struct Token *scanToken(char **str, const struct Token *list);
-	char	*loadData(const char *id, const string& proxy, const string& port,
-			const string &auth, time_t time);
 	void	normalizeData();
 };
 
-#undef NaN
 #endif // _METAR_HXX

Modified: simgear/trunk/simgear/hla/CMakeLists.txt
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/CMakeLists.txt?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/CMakeLists.txt (original)
+++ simgear/trunk/simgear/hla/CMakeLists.txt Sun Jul 15 09:07:01 2012
@@ -7,6 +7,7 @@
     HLABasicDataElement.hxx
     HLABasicDataType.hxx
     HLADataElement.hxx
+    HLADataElementVisitor.hxx
     HLADataType.hxx
     HLADataTypeVisitor.hxx
     HLAEnumeratedDataElement.hxx
@@ -26,15 +27,13 @@
     )
 
 set(HLA_SOURCES
-    RTIObjectClass.cxx
-    RTIObjectInstance.cxx
-    RTIFederate.cxx
     HLAArrayDataElement.cxx
     HLAArrayDataType.cxx
     HLABasicDataElement.cxx
     HLABasicDataType.cxx
     HLADataElement.cxx
     HLADataType.cxx
+    HLADataTypeVisitor.cxx
     HLAEnumeratedDataElement.cxx
     HLAEnumeratedDataType.cxx
     HLAFederate.cxx
@@ -51,15 +50,18 @@
 simgear_component(hla hla "${HLA_SOURCES}" "${HLA_HEADERS}")
 
 if(RTI_FOUND)
-  set(HLA13_HEADERS
-    HLA13Federate.hxx
-    )
-  set(HLA13_SOURCES
+  set(RTI13_SOURCES
     RTI13ObjectClass.cxx
     RTI13ObjectInstance.cxx
     RTI13Federate.cxx
-    HLA13Federate.cxx
     )
-  simgear_component(hla13 hla "${HLA13_SOURCES}" "${HLA13_HEADERS}")
-  set_property(TARGET sghla13 APPEND PROPERTY COMPILE_FLAGS "-I${RTI_INCLUDE_DIR}")
+  simgear_component(rti13 hla "${RTI13_SOURCES}" "")
+  set_property(TARGET sgrti13 APPEND PROPERTY COMPILE_FLAGS "-I${RTI_INCLUDE_DIR}")
 endif()
+
+set(RTI_SOURCES
+  RTIObjectClass.cxx
+  RTIObjectInstance.cxx
+  RTIFederate.cxx
+  )
+simgear_component(rti hla "${RTI_SOURCES}" "")

Modified: simgear/trunk/simgear/hla/HLAArrayDataElement.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAArrayDataElement.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAArrayDataElement.cxx (original)
+++ simgear/trunk/simgear/hla/HLAArrayDataElement.cxx Sun Jul 15 09:07:01 2012
@@ -19,6 +19,8 @@
 
 #include <simgear/debug/logstream.hxx>
 
+#include "HLADataElementVisitor.hxx"
+
 namespace simgear {
 
 HLAAbstractArrayDataElement::HLAAbstractArrayDataElement(const HLAArrayDataType* dataType) :
@@ -28,6 +30,18 @@
 
 HLAAbstractArrayDataElement::~HLAAbstractArrayDataElement()
 {
+}
+
+void
+HLAAbstractArrayDataElement::accept(HLADataElementVisitor& visitor)
+{
+    visitor.apply(*this);
+}
+
+void
+HLAAbstractArrayDataElement::accept(HLAConstDataElementVisitor& visitor) const
+{
+    visitor.apply(*this);
 }
 
 bool

Modified: simgear/trunk/simgear/hla/HLAArrayDataElement.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAArrayDataElement.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAArrayDataElement.hxx (original)
+++ simgear/trunk/simgear/hla/HLAArrayDataElement.hxx Sun Jul 15 09:07:01 2012
@@ -33,6 +33,9 @@
     HLAAbstractArrayDataElement(const HLAArrayDataType* dataType);
     virtual ~HLAAbstractArrayDataElement();
 
+    virtual void accept(HLADataElementVisitor& visitor);
+    virtual void accept(HLAConstDataElementVisitor& visitor) const;
+
     virtual bool decode(HLADecodeStream& stream);
     virtual bool encode(HLAEncodeStream& stream) const;
 
@@ -249,6 +252,43 @@
 };
 
 template<typename T>
+class HLAVec2Data {
+public:
+    HLAVec2Data() :
+        _value(new HLAVec2DataElement<T>(0))
+    { }
+    HLAVec2Data(const SGVec2<T>& value) :
+        _value(new HLAVec2DataElement<T>(0, value))
+    { }
+
+    operator const SGVec2<T>&() const
+    { return _value->getValue(); }
+    HLAVec2Data& operator=(const SGVec2<T>& value)
+    { _value->setValue(value); return *this; }
+
+    const SGVec2<T>& getValue() const
+    { return _value->getValue(); }
+    void setValue(const SGVec2<T>& value)
+    { _value->setValue(value); }
+
+    const HLAVec2DataElement<T>* getDataElement() const
+    { return _value.get(); }
+    HLAVec2DataElement<T>* getDataElement()
+    { return _value.get(); }
+
+    const HLAArrayDataType* getDataType() const
+    { return _value->getDataType(); }
+    void setDataType(const HLAArrayDataType* dataType)
+    { _value->setDataType(dataType); }
+
+private:
+    SGSharedPtr<HLAVec2DataElement<T> > _value;
+};
+
+typedef HLAVec2Data<float> HLAVec2fData;
+typedef HLAVec2Data<double> HLAVec2dData;
+
+template<typename T>
 class HLAVec3DataElement : public HLAAbstractArrayDataElement {
 public:
     HLAVec3DataElement(const HLAArrayDataType* dataType = 0) :
@@ -304,6 +344,43 @@
 };
 
 template<typename T>
+class HLAVec3Data {
+public:
+    HLAVec3Data() :
+        _value(new HLAVec3DataElement<T>(0))
+    { }
+    HLAVec3Data(const SGVec3<T>& value) :
+        _value(new HLAVec3DataElement<T>(0, value))
+    { }
+
+    operator const SGVec3<T>&() const
+    { return _value->getValue(); }
+    HLAVec3Data& operator=(const SGVec3<T>& value)
+    { _value->setValue(value); return *this; }
+
+    const SGVec3<T>& getValue() const
+    { return _value->getValue(); }
+    void setValue(const SGVec3<T>& value)
+    { _value->setValue(value); }
+
+    const HLAVec3DataElement<T>* getDataElement() const
+    { return _value.get(); }
+    HLAVec3DataElement<T>* getDataElement()
+    { return _value.get(); }
+
+    const HLAArrayDataType* getDataType() const
+    { return _value->getDataType(); }
+    void setDataType(const HLAArrayDataType* dataType)
+    { _value->setDataType(dataType); }
+
+private:
+    SGSharedPtr<HLAVec3DataElement<T> > _value;
+};
+
+typedef HLAVec3Data<float> HLAVec3fData;
+typedef HLAVec3Data<double> HLAVec3dData;
+
+template<typename T>
 class HLAVec4DataElement : public HLAAbstractArrayDataElement {
 public:
     HLAVec4DataElement(const HLAArrayDataType* dataType = 0) :
@@ -359,6 +436,43 @@
 };
 
 template<typename T>
+class HLAVec4Data {
+public:
+    HLAVec4Data() :
+        _value(new HLAVec4DataElement<T>(0))
+    { }
+    HLAVec4Data(const SGVec4<T>& value) :
+        _value(new HLAVec4DataElement<T>(0, value))
+    { }
+
+    operator const SGVec4<T>&() const
+    { return _value->getValue(); }
+    HLAVec4Data& operator=(const SGVec4<T>& value)
+    { _value->setValue(value); return *this; }
+
+    const SGVec4<T>& getValue() const
+    { return _value->getValue(); }
+    void setValue(const SGVec4<T>& value)
+    { _value->setValue(value); }
+
+    const HLAVec4DataElement<T>* getDataElement() const
+    { return _value.get(); }
+    HLAVec4DataElement<T>* getDataElement()
+    { return _value.get(); }
+
+    const HLAArrayDataType* getDataType() const
+    { return _value->getDataType(); }
+    void setDataType(const HLAArrayDataType* dataType)
+    { _value->setDataType(dataType); }
+
+private:
+    SGSharedPtr<HLAVec4DataElement<T> > _value;
+};
+
+typedef HLAVec4Data<float> HLAVec4fData;
+typedef HLAVec4Data<double> HLAVec4dData;
+
+template<typename T>
 class HLAQuatDataElement : public HLAAbstractArrayDataElement {
 public:
     HLAQuatDataElement(const HLAArrayDataType* dataType = 0) :

Modified: simgear/trunk/simgear/hla/HLAArrayDataType.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAArrayDataType.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAArrayDataType.cxx (original)
+++ simgear/trunk/simgear/hla/HLAArrayDataType.cxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -22,7 +22,9 @@
 namespace simgear {
 
 HLAArrayDataType::HLAArrayDataType(const std::string& name) :
-    HLADataType(name)
+    HLADataType(name),
+    _isOpaque(false),
+    _isString(false)
 {
 }
 
@@ -49,6 +51,18 @@
     if (getAlignment() < elementDataType->getAlignment())
         setAlignment(elementDataType->getAlignment());
     _elementDataType = elementDataType;
+}
+
+void
+HLAArrayDataType::setIsOpaque(bool isOpaque)
+{
+    _isOpaque = isOpaque;
+}
+
+void
+HLAArrayDataType::setIsString(bool isString)
+{
+    _isString = isString;
 }
 
 ///////////////////////////////////////////////////////////////////////////////////

Modified: simgear/trunk/simgear/hla/HLAArrayDataType.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAArrayDataType.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAArrayDataType.hxx (original)
+++ simgear/trunk/simgear/hla/HLAArrayDataType.hxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -42,8 +42,18 @@
     const HLADataType* getElementDataType() const
     { return _elementDataType.get(); }
 
+    void setIsOpaque(bool isOpaque);
+    bool getIsOpaque() const
+    { return _isOpaque; }
+
+    void setIsString(bool isString);
+    bool getIsString() const
+    { return _isString; }
+
 private:
     SGSharedPtr<const HLADataType> _elementDataType;
+    bool _isOpaque;
+    bool _isString;
 };
 
 class HLAFixedArrayDataType : public HLAArrayDataType {

Modified: simgear/trunk/simgear/hla/HLABasicDataElement.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLABasicDataElement.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLABasicDataElement.cxx (original)
+++ simgear/trunk/simgear/hla/HLABasicDataElement.cxx Sun Jul 15 09:07:01 2012
@@ -17,6 +17,7 @@
 
 #include "HLABasicDataElement.hxx"
 
+#include "HLADataElementVisitor.hxx"
 #include "HLADataTypeVisitor.hxx"
 
 namespace simgear {
@@ -28,6 +29,18 @@
 
 HLABasicDataElement::~HLABasicDataElement()
 {
+}
+
+void
+HLABasicDataElement::accept(HLADataElementVisitor& visitor)
+{
+    visitor.apply(*this);
+}
+
+void
+HLABasicDataElement::accept(HLAConstDataElementVisitor& visitor) const
+{
+    visitor.apply(*this);
 }
 
 const HLABasicDataType*

Modified: simgear/trunk/simgear/hla/HLABasicDataElement.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLABasicDataElement.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLABasicDataElement.hxx (original)
+++ simgear/trunk/simgear/hla/HLABasicDataElement.hxx Sun Jul 15 09:07:01 2012
@@ -28,6 +28,12 @@
     HLABasicDataElement(const HLABasicDataType* dataType);
     virtual ~HLABasicDataElement();
 
+    virtual void accept(HLADataElementVisitor& visitor);
+    virtual void accept(HLAConstDataElementVisitor& visitor) const;
+
+    virtual bool encode(HLAEncodeStream& stream) const = 0;
+    virtual bool decode(HLADecodeStream& stream) = 0;
+
     virtual const HLABasicDataType* getDataType() const;
     virtual bool setDataType(const HLADataType* dataType);
     void setDataType(const HLABasicDataType* dataType);
@@ -41,6 +47,7 @@
 public:                                                                       \
     HLAAbstract##type##DataElement(const HLABasicDataType* dataType = 0);     \
     virtual ~HLAAbstract##type##DataElement();                                \
+                                                                              \
     virtual bool encode(HLAEncodeStream& stream) const;                       \
     virtual bool decode(HLADecodeStream& stream);                             \
                                                                               \

Modified: simgear/trunk/simgear/hla/HLADataElement.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLADataElement.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLADataElement.cxx (original)
+++ simgear/trunk/simgear/hla/HLADataElement.cxx Sun Jul 15 09:07:01 2012
@@ -18,6 +18,8 @@
 #include "HLADataElement.hxx"
 
 #include <simgear/debug/logstream.hxx>
+
+#include "HLADataElementVisitor.hxx"
 
 namespace simgear {
 
@@ -127,6 +129,18 @@
 
 HLADataElement::~HLADataElement()
 {
+}
+
+void
+HLADataElement::accept(HLADataElementVisitor& visitor)
+{
+    visitor.apply(*this);
+}
+
+void
+HLADataElement::accept(HLAConstDataElementVisitor& visitor) const
+{
+    visitor.apply(*this);
 }
 
 std::string

Modified: simgear/trunk/simgear/hla/HLADataElement.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLADataElement.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLADataElement.hxx (original)
+++ simgear/trunk/simgear/hla/HLADataElement.hxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -30,9 +30,15 @@
 
 namespace simgear {
 
+class HLADataElementVisitor;
+class HLAConstDataElementVisitor;
+
 class HLADataElement : public SGReferenced {
 public:
     virtual ~HLADataElement();
+
+    virtual void accept(HLADataElementVisitor& visitor) = 0;
+    virtual void accept(HLAConstDataElementVisitor& visitor) const = 0;
 
     virtual bool encode(HLAEncodeStream& stream) const = 0;
     virtual bool decode(HLADecodeStream& stream) = 0;

Modified: simgear/trunk/simgear/hla/HLADataTypeVisitor.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLADataTypeVisitor.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLADataTypeVisitor.hxx (original)
+++ simgear/trunk/simgear/hla/HLADataTypeVisitor.hxx Sun Jul 15 09:07:01 2012
@@ -24,7 +24,7 @@
 #include <simgear/math/SGMath.hxx>
 #include "HLAArrayDataType.hxx"
 #include "HLABasicDataType.hxx"
-#include "HLADataTypeVisitor.hxx"
+#include "HLADataElement.hxx"
 #include "HLAEnumeratedDataType.hxx"
 #include "HLAFixedRecordDataType.hxx"
 #include "HLAVariantDataType.hxx"
@@ -629,6 +629,43 @@
     dataType.getSizeDataType()->accept(numElementsVisitor);
 }
 
+/// Generate standard data elements according to the traversed type
+class HLADataElementFactoryVisitor : public HLADataTypeVisitor {
+public:
+    virtual ~HLADataElementFactoryVisitor();
+
+    virtual void apply(const HLADataType& dataType);
+
+    virtual void apply(const HLAInt8DataType& dataType);
+    virtual void apply(const HLAUInt8DataType& dataType);
+    virtual void apply(const HLAInt16DataType& dataType);
+    virtual void apply(const HLAUInt16DataType& dataType);
+    virtual void apply(const HLAInt32DataType& dataType);
+    virtual void apply(const HLAUInt32DataType& dataType);
+    virtual void apply(const HLAInt64DataType& dataType);
+    virtual void apply(const HLAUInt64DataType& dataType);
+    virtual void apply(const HLAFloat32DataType& dataType);
+    virtual void apply(const HLAFloat64DataType& dataType);
+
+    virtual void apply(const HLAFixedArrayDataType& dataType);
+    virtual void apply(const HLAVariableArrayDataType& dataType);
+
+    virtual void apply(const HLAEnumeratedDataType& dataType);
+
+    virtual void apply(const HLAFixedRecordDataType& dataType);
+
+    virtual void apply(const HLAVariantDataType& dataType);
+
+    HLADataElement* getDataElement()
+    { return _dataElement.release(); }
+
+protected:
+    class ArrayDataElementFactory;
+    class VariantDataElementFactory;
+
+    SGSharedPtr<HLADataElement> _dataElement;
+};
+
 } // namespace simgear
 
 #endif

Modified: simgear/trunk/simgear/hla/HLAEnumeratedDataElement.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAEnumeratedDataElement.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAEnumeratedDataElement.cxx (original)
+++ simgear/trunk/simgear/hla/HLAEnumeratedDataElement.cxx Sun Jul 15 09:07:01 2012
@@ -19,6 +19,8 @@
 
 #include <simgear/debug/logstream.hxx>
 
+#include "HLADataElementVisitor.hxx"
+
 namespace simgear {
 
 HLAAbstractEnumeratedDataElement::HLAAbstractEnumeratedDataElement(const HLAEnumeratedDataType* dataType) :
@@ -28,6 +30,18 @@
 
 HLAAbstractEnumeratedDataElement::~HLAAbstractEnumeratedDataElement()
 {
+}
+
+void
+HLAAbstractEnumeratedDataElement::accept(HLADataElementVisitor& visitor)
+{
+    visitor.apply(*this);
+}
+
+void
+HLAAbstractEnumeratedDataElement::accept(HLAConstDataElementVisitor& visitor) const
+{
+    visitor.apply(*this);
 }
 
 bool

Modified: simgear/trunk/simgear/hla/HLAEnumeratedDataElement.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAEnumeratedDataElement.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAEnumeratedDataElement.hxx (original)
+++ simgear/trunk/simgear/hla/HLAEnumeratedDataElement.hxx Sun Jul 15 09:07:01 2012
@@ -27,6 +27,9 @@
 public:
     HLAAbstractEnumeratedDataElement(const HLAEnumeratedDataType* dataType);
     virtual ~HLAAbstractEnumeratedDataElement();
+
+    virtual void accept(HLADataElementVisitor& visitor);
+    virtual void accept(HLAConstDataElementVisitor& visitor) const;
 
     virtual bool decode(HLADecodeStream& stream);
     virtual bool encode(HLAEncodeStream& stream) const;

Modified: simgear/trunk/simgear/hla/HLAFederate.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAFederate.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAFederate.cxx (original)
+++ simgear/trunk/simgear/hla/HLAFederate.cxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -17,6 +17,7 @@
 
 #include "HLAFederate.hxx"
 
+#include "RTI13Federate.hxx"
 #include "RTIFederate.hxx"
 #include "RTIInteractionClass.hxx"
 #include "RTIObjectClass.hxx"
@@ -26,97 +27,721 @@
 
 namespace simgear {
 
-HLAFederate::HLAFederate(const SGSharedPtr<RTIFederate>& rtiFederate) :
-    _rtiFederate(rtiFederate)
+HLAFederate::HLAFederate() :
+    _version(RTI13),
+    _createFederationExecution(true),
+    _timeConstrained(false),
+    _timeRegulating(false),
+    _timeConstrainedByLocalClock(false),
+    _done(false)
 {
 }
 
 HLAFederate::~HLAFederate()
 {
+}
+
+HLAFederate::Version
+HLAFederate::getVersion() const
+{
+    return _version;
+}
+
+bool
+HLAFederate::setVersion(HLAFederate::Version version)
+{
+    if (_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
+        return false;
+    }
+    _version = version;
+    return true;
+}
+
+const std::list<std::string>&
+HLAFederate::getConnectArguments() const
+{
+    return _connectArguments;
+}
+
+bool
+HLAFederate::setConnectArguments(const std::list<std::string>& connectArguments)
+{
+    if (_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
+        return false;
+    }
+    _connectArguments = connectArguments;
+    return true;
+}
+
+bool
+HLAFederate::getCreateFederationExecution() const
+{
+    return _createFederationExecution;
+}
+
+bool
+HLAFederate::setCreateFederationExecution(bool createFederationExecution)
+{
+    _createFederationExecution = createFederationExecution;
+    return true;
+}
+
+const std::string&
+HLAFederate::getFederationExecutionName() const
+{
+    return _federationExecutionName;
+}
+
+bool
+HLAFederate::setFederationExecutionName(const std::string& federationExecutionName)
+{
+    if (_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
+        return false;
+    }
+    _federationExecutionName = federationExecutionName;
+    return true;
+}
+
+const std::string&
+HLAFederate::getFederationObjectModel() const
+{
+    return _federationObjectModel;
+}
+
+bool
+HLAFederate::setFederationObjectModel(const std::string& federationObjectModel)
+{
+    if (_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
+        return false;
+    }
+    _federationObjectModel = federationObjectModel;
+    return true;
 }
 
 const std::string&
 HLAFederate::getFederateType() const
 {
-    return _rtiFederate->getFederateType();
+    return _federateType;
+}
+
+bool
+HLAFederate::setFederateType(const std::string& federateType)
+{
+    if (_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
+        return false;
+    }
+    _federateType = federateType;
+    return true;
 }
 
 const std::string&
-HLAFederate::getFederationName() const
-{
-    return _rtiFederate->getFederationName();
+HLAFederate::getFederateName() const
+{
+    return _federateName;
+}
+
+bool
+HLAFederate::setFederateName(const std::string& federateName)
+{
+    if (_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
+        return false;
+    }
+    _federateName = federateName;
+    return true;
+}
+
+bool
+HLAFederate::connect(Version version, const std::list<std::string>& stringList)
+{
+    if (_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
+        return false;
+    }
+    switch (version) {
+    case RTI13:
+        _rtiFederate = new RTI13Federate(stringList);
+        _version = version;
+        _connectArguments = stringList;
+        break;
+    case RTI1516:
+        SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported.");
+        // _rtiFederate = new RTI1516Federate(stringList);
+        break;
+    case RTI1516E:
+        SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
+        // _rtiFederate = new RTI1516eFederate(stringList);
+        break;
+    default:
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
+    }
+    return _rtiFederate.valid();
+}
+
+bool
+HLAFederate::connect()
+{
+    if (_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
+        return false;
+    }
+    switch (_version) {
+    case RTI13:
+        _rtiFederate = new RTI13Federate(_connectArguments);
+        break;
+    case RTI1516:
+        SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported.");
+        // _rtiFederate = new RTI1516Federate(_connectArguments);
+        break;
+    case RTI1516E:
+        SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
+        // _rtiFederate = new RTI1516eFederate(_connectArguments);
+        break;
+    default:
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
+    }
+    return _rtiFederate.valid();
+}
+
+bool
+HLAFederate::disconnect()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+    _rtiFederate = 0;
+    return true;
 }
 
 bool
 HLAFederate::createFederationExecution(const std::string& federation, const std::string& objectModel)
 {
-    return _rtiFederate->createFederationExecution(federation, objectModel);
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    RTIFederate::FederationManagementResult createResult;
+    createResult = _rtiFederate->createFederationExecution(federation, objectModel);
+    if (createResult == RTIFederate::FederationManagementFatal)
+        return false;
+
+    _federationExecutionName = federation;
+    _federationObjectModel = objectModel;
+    return true;
 }
 
 bool
 HLAFederate::destroyFederationExecution(const std::string& federation)
 {
-    return _rtiFederate->destroyFederationExecution(federation);
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    RTIFederate::FederationManagementResult destroyResult;
+    destroyResult = _rtiFederate->destroyFederationExecution(federation);
+    if (destroyResult == RTIFederate::FederationManagementFatal)
+        return false;
+
+    return true;
+}
+
+bool
+HLAFederate::createFederationExecution()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    RTIFederate::FederationManagementResult createResult;
+    createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
+    if (createResult != RTIFederate::FederationManagementSuccess)
+        return false;
+
+    return true;
+}
+
+bool
+HLAFederate::destroyFederationExecution()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    RTIFederate::FederationManagementResult destroyResult;
+    destroyResult = _rtiFederate->destroyFederationExecution(_federationExecutionName);
+    if (destroyResult != RTIFederate::FederationManagementSuccess)
+        return false;
+
+    return true;
 }
 
 bool
 HLAFederate::join(const std::string& federateType, const std::string& federation)
 {
-    return _rtiFederate->join(federateType, federation);
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    RTIFederate::FederationManagementResult joinResult;
+    joinResult = _rtiFederate->join(federateType, federation);
+    if (joinResult == RTIFederate::FederationManagementFatal)
+        return false;
+
+    return true;
+}
+
+bool
+HLAFederate::join()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    RTIFederate::FederationManagementResult joinResult;
+    joinResult = _rtiFederate->join(_federateType, _federationExecutionName);
+    if (joinResult != RTIFederate::FederationManagementSuccess)
+        return false;
+
+    return true;
 }
 
 bool
 HLAFederate::resign()
 {
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
     return _rtiFederate->resign();
 }
 
 bool
+HLAFederate::createJoinFederationExecution()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    for (;;) {
+        // Try to join.
+        RTIFederate::FederationManagementResult joinResult;
+        joinResult = _rtiFederate->join(_federateType, _federationExecutionName);
+        switch (joinResult) {
+        case RTIFederate::FederationManagementSuccess:
+            // Fast return on success
+            return true;
+        case RTIFederate::FederationManagementFatal:
+            // Abort on fatal errors
+            return false;
+        default:
+            break;
+        };
+
+        // If not already joinable, try to create the requested federation
+        RTIFederate::FederationManagementResult createResult;
+        createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
+        switch (createResult) {
+        case RTIFederate::FederationManagementFatal:
+            // Abort on fatal errors
+            return false;
+        default:
+            // Try again to join
+            break;
+        }
+    }
+}
+
+bool
+HLAFederate::resignDestroyFederationExecution()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+    
+    // Resign ourselves
+    bool success = _rtiFederate->resign();
+
+    // and try to destroy, non fatal if still some federates joined
+    if (_rtiFederate->destroyFederationExecution(_federationExecutionName) == RTIFederate::FederationManagementFatal)
+        success = false;
+
+    return success;
+}
+
+bool
+HLAFederate::getTimeConstrained() const
+{
+    return _timeConstrained;
+}
+
+bool
+HLAFederate::setTimeConstrained(bool timeConstrained)
+{
+    _timeConstrained = timeConstrained;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (_timeConstrained && !_rtiFederate->getTimeConstrainedEnabled()) {
+            if (!enableTimeConstrained())
+                return false;
+        } else if (!_timeConstrained && _rtiFederate->getTimeConstrainedEnabled()) {
+            if (!disableTimeConstrained())
+                return false;
+        }
+
+    }
+
+    return true;
+}
+
+bool
+HLAFederate::getTimeConstrainedByLocalClock() const
+{
+    return _timeConstrainedByLocalClock;
+}
+
+bool
+HLAFederate::setTimeConstrainedByLocalClock(bool timeConstrainedByLocalClock)
+{
+    _timeConstrainedByLocalClock = timeConstrainedByLocalClock;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (_timeConstrainedByLocalClock) {
+            if (!enableTimeConstrainedByLocalClock())
+                return false;
+        }
+    }
+
+    return true;
+}
+
+bool
+HLAFederate::getTimeRegulating() const
+{
+    return _timeRegulating;
+}
+
+bool
+HLAFederate::setTimeRegulating(bool timeRegulating)
+{
+    _timeRegulating = timeRegulating;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (_timeRegulating && !_rtiFederate->getTimeRegulationEnabled()) {
+            if (!enableTimeRegulation())
+                return false;
+        } else if (!_timeRegulating && _rtiFederate->getTimeRegulationEnabled()) {
+            if (!disableTimeRegulation())
+                return false;
+        }
+
+    }
+    return true;
+}
+
+bool
+HLAFederate::setLeadTime(const SGTimeStamp& leadTime)
+{
+    if (leadTime < SGTimeStamp::fromSec(0)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Ignoring negative lead time!");
+        return false;
+    }
+
+    _leadTime = leadTime;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
+            SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
+            return false;
+        }
+    }
+
+    return true;
+}
+
+const SGTimeStamp&
+HLAFederate::getLeadTime() const
+{
+    return _leadTime;
+}
+
+bool
+HLAFederate::setTimeIncrement(const SGTimeStamp& timeIncrement)
+{
+    if (timeIncrement < SGTimeStamp::fromSec(0)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Ignoring negative time increment!");
+        return false;
+    }
+
+    _timeIncrement = timeIncrement;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
+            SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
+            return false;
+        }
+    }
+
+    return true;
+}
+
+const SGTimeStamp&
+HLAFederate::getTimeIncrement() const
+{
+    return _timeIncrement;
+}
+
+bool
 HLAFederate::enableTimeConstrained()
 {
-    return _rtiFederate->enableTimeConstrained();
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    if (!_rtiFederate->enableTimeConstrained()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time constrained!");
+        return false;
+    }
+
+    while (!_rtiFederate->getTimeConstrainedEnabled()) {
+        _rtiFederate->processMessage();
+    }
+
+    return true;
 }
 
 bool
 HLAFederate::disableTimeConstrained()
 {
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
     return _rtiFederate->disableTimeConstrained();
 }
 
 bool
+HLAFederate::enableTimeConstrainedByLocalClock()
+{
+    // Compute the time offset from the system time to the simulation time
+    SGTimeStamp federateTime;
+    if (!queryFederateTime(federateTime)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Cannot get federate time!");
+        return false;
+    }
+    _localClockOffset = SGTimeStamp::now() - federateTime;
+    return true;
+}
+
+bool
 HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
 {
-    return _rtiFederate->enableTimeRegulation(lookahead);
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    if (!_rtiFederate->enableTimeRegulation(lookahead)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time regulation!");
+        return false;
+    }
+
+    while (!_rtiFederate->getTimeRegulationEnabled()) {
+        _rtiFederate->processMessage();
+    }
+
+    return true;
+}
+
+bool
+HLAFederate::enableTimeRegulation()
+{
+    if (!enableTimeRegulation(SGTimeStamp::fromSec(0))) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time regulation!");
+        return false;
+    }
+    if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
+        return false;
+    }
+    return true;
 }
 
 bool
 HLAFederate::disableTimeRegulation()
 {
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
     return _rtiFederate->disableTimeRegulation();
 }
 
 bool
-HLAFederate::timeAdvanceRequestBy(const SGTimeStamp& dt)
-{
-    return _rtiFederate->timeAdvanceRequestBy(dt);
-}
-
-bool
-HLAFederate::timeAdvanceRequest(const SGTimeStamp& dt)
-{
-    return _rtiFederate->timeAdvanceRequest(dt);
-}
-
-bool
-HLAFederate::tick()
-{
-    return _rtiFederate->tick();
+HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp)
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+    return _rtiFederate->modifyLookahead(timeStamp);
+}
+
+bool
+HLAFederate::timeAdvanceBy(const SGTimeStamp& timeIncrement)
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    SGTimeStamp timeStamp;
+    if (!_rtiFederate->queryFederateTime(timeStamp)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query federate time!");
+        return false;
+    }
+
+    if (!_rtiFederate->timeAdvanceRequest(timeStamp + timeIncrement)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
+        return false;
+    }
+
+    return processMessages();
+}
+
+bool
+HLAFederate::timeAdvance(const SGTimeStamp& timeStamp)
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    if (!_rtiFederate->timeAdvanceRequest(timeStamp)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
+        return false;
+    }
+
+    return processMessages();
+}
+
+bool
+HLAFederate::timeAdvanceAvailable()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    SGTimeStamp timeStamp;
+    if (!_rtiFederate->queryGALT(timeStamp)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query GALT!");
+        return false;
+    }
+
+    if (!_rtiFederate->timeAdvanceRequestAvailable(timeStamp)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
+        return false;
+    }
+
+    return processMessages();
+}
+
+bool
+HLAFederate::queryFederateTime(SGTimeStamp& timeStamp)
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+    return _rtiFederate->queryFederateTime(timeStamp);
+}
+
+bool
+HLAFederate::queryLookahead(SGTimeStamp& timeStamp)
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+    return _rtiFederate->queryLookahead(timeStamp);
+}
+
+bool
+HLAFederate::processMessage()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+    return _rtiFederate->processMessage();
+}
+
+bool
+HLAFederate::processMessage(const SGTimeStamp& timeout)
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+    return _rtiFederate->processMessages(timeout.toSecs(), 0);
+}
+
+bool
+HLAFederate::processMessages()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+
+    while (_rtiFederate->getTimeAdvancePending()) {
+        _rtiFederate->processMessage();
+    }
+
+    if (_timeConstrainedByLocalClock) {
+        SGTimeStamp federateTime;
+        if (!_rtiFederate->queryFederateTime(federateTime)) {
+            SG_LOG(SG_NETWORK, SG_WARN, "HLA: Error querying federate time!");
+            return false;
+        }
+        SGTimeStamp systemTime = federateTime + _localClockOffset;
+        for (;;) {
+            double rest = (systemTime - SGTimeStamp::now()).toSecs();
+            if (rest < 0)
+                break;
+            _rtiFederate->processMessages(rest, rest);
+        }
+    }
+    
+    // Now flush just what is left
+    while (_rtiFederate->processMessages(0, 0));
+
+    return true;
 }
 
 bool
 HLAFederate::tick(const double& minimum, const double& maximum)
 {
-    return _rtiFederate->tick(minimum, maximum);
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
+    return _rtiFederate->processMessages(minimum, maximum);
 }
 
 bool
@@ -124,8 +749,7 @@
                                      HLAFederate::ObjectModelFactory& objectModelFactory)
 {
     if (!_rtiFederate.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Could not process HLA XML object model file: "
-               "No rti federate available!");
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
         return false;
     }
 
@@ -243,4 +867,146 @@
     return i->second.get();
 }
 
+void
+HLAFederate::setDone(bool done)
+{
+    _done = done;
+}
+
+bool
+HLAFederate::getDone() const
+{
+    return _done;
+}
+
+bool
+HLAFederate::readObjectModel()
+{
+    /// Currently empty, but is called at the right time so that
+    /// the object model is present when it is needed
+    return true;
+}
+
+bool
+HLAFederate::subscribe()
+{
+    /// Currently empty, but is called at the right time
+    return true;
+}
+
+bool
+HLAFederate::publish()
+{
+    /// Currently empty, but is called at the right time
+    return true;
+}
+
+bool
+HLAFederate::init()
+{
+    // We need to talk to the rti
+    if (!connect())
+        return false;
+    // Join ...
+    if (_createFederationExecution) {
+        if (!createJoinFederationExecution())
+            return false;
+    } else {
+        if (!join())
+            return false;
+    }
+    // Read the xml file containing the object model
+    if (!readObjectModel()) {
+        shutdown();
+        return false;
+    }
+    // start being time constrained if required
+    if (_timeConstrained) {
+        if (!enableTimeConstrained()) {
+            shutdown();
+            return false;
+        }
+    }
+    // Now that we are potentially time constrained, we can subscribe.
+    // This is to make sure we do not get any time stamped message
+    // converted to a non time stamped message by the rti.
+    if (!subscribe()) {
+        shutdown();
+        return false;
+    }
+    // Before we publish anything start getting regulating if required
+    if (_timeRegulating) {
+        if (!enableTimeRegulation()) {
+            shutdown();
+            return false;
+        }
+    }
+    // Note that starting from here, we need to be careful with things
+    // requireing unbounded time. The rest of the federation might wait
+    // for us to finish!
+    
+    // Compute the time offset from the system time to the simulation time
+    if (_timeConstrainedByLocalClock) {
+        if (!enableTimeConstrainedByLocalClock()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time constrained by local clock!");
+            shutdown();
+            return false;
+        }
+    }
+    
+    // Publish what we want to write
+    if (!publish()) {
+        shutdown();
+        return false;
+    }
+    
+    return true;
+}
+
+bool
+HLAFederate::update()
+{
+    return timeAdvanceBy(_timeIncrement);
+}
+
+bool
+HLAFederate::shutdown()
+{
+    // On shutdown, just try all in order.
+    // If something goes wrong, continue and try to get out here as good as possible.
+    bool ret = true;
+    
+    if (_createFederationExecution) {
+        if (!resignDestroyFederationExecution())
+            ret = false;
+    } else {
+        if (!resign())
+            ret = false;
+    }
+    
+    if (!disconnect())
+        ret = false;
+    
+    return ret;
+}
+
+bool
+HLAFederate::exec()
+{
+    if (!init())
+        return false;
+    
+    while (!getDone()) {
+        if (!update()) {
+            shutdown();
+            return false;
+        }
+    }
+    
+    if (!shutdown())
+        return false;
+    
+    return true;
+}
+
 } // namespace simgear

Modified: simgear/trunk/simgear/hla/HLAFederate.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAFederate.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAFederate.hxx (original)
+++ simgear/trunk/simgear/hla/HLAFederate.hxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -32,34 +32,136 @@
 
 class HLAFederate : public SGWeakReferenced {
 public:
+    HLAFederate();
     virtual ~HLAFederate();
 
-    /// Get the name of the joined federate/federation
+    enum Version {
+        RTI13,
+        RTI1516,
+        RTI1516E
+    };
+
+    /// The rti version backend to connect
+    Version getVersion() const;
+    bool setVersion(HLAFederate::Version version);
+
+    /// The rti backends connect arguments, depends on the version
+    const std::list<std::string>& getConnectArguments() const;
+    bool setConnectArguments(const std::list<std::string>& connectArguments);
+
+    /// If true try to create on join and try to destroy on resign
+    bool getCreateFederationExecution() const;
+    bool setCreateFederationExecution(bool createFederationExecution);
+
+    /// The federation execution name to use on create, join and destroy
+    const std::string& getFederationExecutionName() const;
+    bool setFederationExecutionName(const std::string& federationExecutionName);
+
+    /// The federation object model name to use on create and possibly join
+    const std::string& getFederationObjectModel() const;
+    bool setFederationObjectModel(const std::string& federationObjectModel);
+
+    /// The federate type used on join
     const std::string& getFederateType() const;
-    const std::string& getFederationName() const;
+    bool setFederateType(const std::string& federateType);
+
+    /// The federate name possibly used on join
+    const std::string& getFederateName() const;
+    bool setFederateName(const std::string& federateName);
+
+    /// connect to an rti
+    bool connect(Version version, const std::list<std::string>& stringList);
+    bool connect();
+    bool disconnect();
 
     /// Create a federation execution
     /// Semantically this methods should be static,
     /// but the nonstatic case could reuse the connection to the server
-    /// FIXME: cannot determine from the return value if we created the execution
     bool createFederationExecution(const std::string& federation, const std::string& objectModel);
     bool destroyFederationExecution(const std::string& federation);
+    bool createFederationExecution();
+    bool destroyFederationExecution();
 
     /// Join with federateType the federation execution
     bool join(const std::string& federateType, const std::string& federation);
+    bool join();
     bool resign();
-
+    
+    /// Try to create and join the federation execution.
+    bool createJoinFederationExecution();
+    bool resignDestroyFederationExecution();
+
+
+    /// Time management
+
+    /// If set to true, time constrained mode is entered on init
+    bool getTimeConstrained() const;
+    bool setTimeConstrained(bool timeConstrained);
+
+    /// If set to true, time advance is constrained by the local system clock
+    bool getTimeConstrainedByLocalClock() const;
+    bool setTimeConstrainedByLocalClock(bool timeConstrainedByLocalClock);
+
+    /// If set to true, time regulation mode is entered on init
+    bool getTimeRegulating() const;
+    bool setTimeRegulating(bool timeRegulating);
+
+    /// If set to a non zero value, this federate leads the federations
+    /// locical time advance by this amount of time.
+    const SGTimeStamp& getLeadTime() const;
+    bool setLeadTime(const SGTimeStamp& leadTime);
+
+    /// The time increment for use in the default update method.
+    const SGTimeStamp& getTimeIncrement() const;
+    bool setTimeIncrement(const SGTimeStamp& timeIncrement);
+
+    /// Actually enable time constrained mode.
+    /// This method blocks until time constrained mode is enabled.
     bool enableTimeConstrained();
+    /// Actually disable time constrained mode.
     bool disableTimeConstrained();
 
+    /// Actually enable time constrained by local clock mode.
+    bool enableTimeConstrainedByLocalClock();
+
+    /// Actually enable time regulation mode.
+    /// This method blocks until time regulation mode is enabled.
     bool enableTimeRegulation(const SGTimeStamp& lookahead);
+    bool enableTimeRegulation();
+    /// Actually disable time regulation mode.
     bool disableTimeRegulation();
-
-    bool timeAdvanceRequestBy(const SGTimeStamp& dt);
-    bool timeAdvanceRequest(const SGTimeStamp& dt);
-
-    /// Process messages
-    bool tick();
+    /// Actually modify the lookahead time.
+    bool modifyLookahead(const SGTimeStamp& lookahead);
+
+    /// Advance the logical time by the given time increment.
+    /// Depending on the time constrained mode, this might
+    /// block until the time advance is granted.
+    bool timeAdvanceBy(const SGTimeStamp& timeIncrement);
+    /// Advance the logical time to the given time.
+    /// Depending on the time constrained mode, this might
+    /// block until the time advance is granted.
+    bool timeAdvance(const SGTimeStamp& timeStamp);
+    /// Advance the logical time as far as time advances are available.
+    /// This call should not block and advance the logical time
+    /// as far as currently possible.
+    bool timeAdvanceAvailable();
+
+    /// Get the current federates time
+    bool queryFederateTime(SGTimeStamp& timeStamp);
+    /// Get the current federates lookahead
+    bool queryLookahead(SGTimeStamp& timeStamp);
+
+    /// Process one messsage
+    bool processMessage();
+    /// Process one message but do not wait longer than the relative timeout.
+    bool processMessage(const SGTimeStamp& timeout);
+    /// Process messages until the federate can proceed with the
+    /// next simulation step. That is flush all pending messages and
+    /// depending on the time constrained mode process messages until
+    /// a pending time advance is granted.
+    bool processMessages();
+
+    /// Legacy tick call
     bool tick(const double& minimum, const double& maximum);
 
     class ObjectModelFactory {
@@ -84,17 +186,66 @@
     bool readObjectModelTemplate(const std::string& objectModel,
                                  ObjectModelFactory& objectModelFactory);
 
+    /// Get the object class of a given name
     HLAObjectClass* getObjectClass(const std::string& name);
     const HLAObjectClass* getObjectClass(const std::string& name) const;
 
+    /// Get the interaction class of a given name
     HLAInteractionClass* getInteractionClass(const std::string& name);
     const HLAInteractionClass* getInteractionClass(const std::string& name) const;
 
-protected:
-    HLAFederate(const SGSharedPtr<RTIFederate>& rtiFederate);
+    /// Tells the main exec loop to continue or not.
+    void setDone(bool done);
+    bool getDone() const;
+
+    virtual bool readObjectModel();
+
+    virtual bool subscribe();
+    virtual bool publish();
+
+    virtual bool init();
+    virtual bool update();
+    virtual bool shutdown();
+
+    virtual bool exec();
 
 private:
+    HLAFederate(const HLAFederate&);
+    HLAFederate& operator=(const HLAFederate&);
+
+    /// The underlying interface to the rti implementation
     SGSharedPtr<RTIFederate> _rtiFederate;
+
+    /// Parameters required to connect to an rti
+    Version _version;
+    std::list<std::string> _connectArguments;
+
+    /// Parameters for the federation execution
+    std::string _federationExecutionName;
+    std::string _federationObjectModel;
+    bool _createFederationExecution;
+
+    /// Parameters for the federate
+    std::string _federateType;
+    std::string _federateName;
+
+    /// Time management related parameters
+    /// If true, the federate is expected to enter time constrained mode
+    bool _timeConstrained;
+    /// If true, the federate is expected to enter time regulating mode
+    bool _timeRegulating;
+    /// The amount of time this federate leads the others.
+    SGTimeStamp _leadTime;
+    /// The regular time increment we do on calling update()
+    SGTimeStamp _timeIncrement;
+    /// The reference system time at initialization time.
+    /// Is used to implement being time constrained on the
+    /// local system time.
+    bool _timeConstrainedByLocalClock;
+    SGTimeStamp _localClockOffset;
+
+    /// If true the exec method returns.
+    bool _done;
 
     typedef std::map<std::string, SGSharedPtr<HLAObjectClass> > ObjectClassMap;
     ObjectClassMap _objectClassMap;

Modified: simgear/trunk/simgear/hla/HLAFixedRecordDataElement.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAFixedRecordDataElement.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAFixedRecordDataElement.cxx (original)
+++ simgear/trunk/simgear/hla/HLAFixedRecordDataElement.cxx Sun Jul 15 09:07:01 2012
@@ -20,6 +20,8 @@
 #include <string>
 #include <vector>
 #include <simgear/debug/logstream.hxx>
+
+#include "HLADataElementVisitor.hxx"
 #include "HLADataTypeVisitor.hxx"
 
 namespace simgear {
@@ -31,6 +33,18 @@
 
 HLAAbstractFixedRecordDataElement::~HLAAbstractFixedRecordDataElement()
 {
+}
+
+void
+HLAAbstractFixedRecordDataElement::accept(HLADataElementVisitor& visitor)
+{
+    visitor.apply(*this);
+}
+
+void
+HLAAbstractFixedRecordDataElement::accept(HLAConstDataElementVisitor& visitor) const
+{
+    visitor.apply(*this);
 }
 
 bool

Modified: simgear/trunk/simgear/hla/HLAFixedRecordDataElement.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAFixedRecordDataElement.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAFixedRecordDataElement.hxx (original)
+++ simgear/trunk/simgear/hla/HLAFixedRecordDataElement.hxx Sun Jul 15 09:07:01 2012
@@ -29,6 +29,9 @@
 public:
     HLAAbstractFixedRecordDataElement(const HLAFixedRecordDataType* dataType);
     virtual ~HLAAbstractFixedRecordDataElement();
+
+    virtual void accept(HLADataElementVisitor& visitor);
+    virtual void accept(HLAConstDataElementVisitor& visitor) const;
 
     virtual bool decode(HLADecodeStream& stream);
     virtual bool encode(HLAEncodeStream& stream) const;

Modified: simgear/trunk/simgear/hla/HLAInteractionClass.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAInteractionClass.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAInteractionClass.hxx (original)
+++ simgear/trunk/simgear/hla/HLAInteractionClass.hxx Sun Jul 15 09:07:01 2012
@@ -25,6 +25,10 @@
 class HLAInteractionClass : public SGWeakReferenced {
 public:
     virtual ~HLAInteractionClass() {}
+
+private:
+    HLAInteractionClass(const HLAInteractionClass&);
+    HLAInteractionClass& operator=(const HLAInteractionClass&);
 };
 
 } // namespace simgear

Modified: simgear/trunk/simgear/hla/HLAOMTXmlVisitor.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAOMTXmlVisitor.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAOMTXmlVisitor.cxx (original)
+++ simgear/trunk/simgear/hla/HLAOMTXmlVisitor.cxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -439,6 +439,15 @@
     }
     arrayDataType->setElementDataType(elementDataType.get());
 
+    // Check if this should be a string data type
+    if (elementDataType->toBasicDataType()) {
+        if (dataTypeName == "HLAopaqueData") {
+            arrayDataType->setIsOpaque(true);
+        } else if (dataTypeName.find("String") != std::string::npos || dataTypeName.find("string") != std::string::npos) {
+            arrayDataType->setIsString(true);
+        }
+    }
+
     return arrayDataType;
 }
 

Modified: simgear/trunk/simgear/hla/HLAObjectClass.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAObjectClass.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAObjectClass.hxx (original)
+++ simgear/trunk/simgear/hla/HLAObjectClass.hxx Sun Jul 15 09:07:01 2012
@@ -95,6 +95,9 @@
     virtual HLAObjectInstance* createObjectInstance(RTIObjectInstance* rtiObjectInstance);
 
 private:
+    HLAObjectClass(const HLAObjectClass&);
+    HLAObjectClass& operator=(const HLAObjectClass&);
+
     // The internal entry points from the RTILObjectClass callback functions
     void discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag);
     void removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag);

Modified: simgear/trunk/simgear/hla/HLAObjectInstance.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAObjectInstance.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAObjectInstance.cxx (original)
+++ simgear/trunk/simgear/hla/HLAObjectInstance.cxx Sun Jul 15 09:07:01 2012
@@ -123,7 +123,7 @@
     return _rtiObjectInstance->getDataElement(index);
 }
 
-class HLAObjectInstance::DataElementFactoryVisitor : public HLADataTypeVisitor {
+class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
 public:
     DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
         _pathElementMap(pathElementMap)
@@ -150,7 +150,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLASCharDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAUInt8DataType& dataType)
     {
@@ -158,7 +158,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAUCharDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAInt16DataType& dataType)
     {
@@ -166,7 +166,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAShortDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAUInt16DataType& dataType)
     {
@@ -174,7 +174,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAUShortDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAInt32DataType& dataType)
     {
@@ -182,7 +182,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAIntDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAUInt32DataType& dataType)
     {
@@ -190,7 +190,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAUIntDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAInt64DataType& dataType)
     {
@@ -198,7 +198,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLALongDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAUInt64DataType& dataType)
     {
@@ -206,7 +206,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAULongDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAFloat32DataType& dataType)
     {
@@ -214,7 +214,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAFloatDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
     virtual void apply(const HLAFloat64DataType& dataType)
     {
@@ -222,7 +222,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLADoubleDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
 
     class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
@@ -287,7 +287,7 @@
         if (_dataElement.valid())
             return;
 
-        _dataElement = new HLAEnumeratedDataElement(&dataType);
+        HLADataElementFactoryVisitor::apply(dataType);
     }
 
     virtual void apply(const HLAFixedRecordDataType& dataType)
@@ -357,9 +357,6 @@
         _dataElement = variantDataElement;
     }
 
-    const SGSharedPtr<HLADataElement>& getDataElement() const
-    { return _dataElement; }
-
 private:
     SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
     {
@@ -381,7 +378,6 @@
         return dataElement;
     }
 
-    SGSharedPtr<HLADataElement> _dataElement;
     const HLAPathElementMap& _pathElementMap;
     HLADataElement::Path _path;
 };
@@ -414,26 +410,6 @@
 }
 
 void
-HLAObjectInstance::requestAttributeUpdate(unsigned index)
-{
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
-        return;
-    }
-    _rtiObjectInstance->setRequestAttributeUpdate(index, true);
-}
-
-void
-HLAObjectInstance::requestAttributeUpdate()
-{
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!");
-        return;
-    }
-    _rtiObjectInstance->setRequestAttributeUpdate(true);
-}
-
-void
 HLAObjectInstance::registerInstance()
 {
     if (_rtiObjectInstance.valid()) {
@@ -472,16 +448,6 @@
 }
 
 void
-HLAObjectInstance::localDeleteInstance()
-{
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
-        return;
-    }
-   _rtiObjectInstance->localDeleteObjectInstance();
-}
-
-void
 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
 {
     if (!_rtiObjectInstance.valid()) {
@@ -506,16 +472,6 @@
 }
 
 void
-HLAObjectInstance::reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
-{
-    if (!_rtiObjectInstance.valid()) {
-        SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
-        return;
-    }
-    _rtiObjectInstance->reflectQueuedAttributeValues(timeStamp);
-}
-
-void
 HLAObjectInstance::removeInstance(const RTIData& tag)
 {
     SGSharedPtr<HLAObjectClass> objectClass = _objectClass.lock();

Modified: simgear/trunk/simgear/hla/HLAObjectInstance.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAObjectInstance.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAObjectInstance.hxx (original)
+++ simgear/trunk/simgear/hla/HLAObjectInstance.hxx Sun Jul 15 09:07:01 2012
@@ -52,13 +52,8 @@
     void setAttribute(unsigned index, const HLAPathElementMap& pathElementMap);
     void setAttributes(const HLAAttributePathElementMap& attributePathElementMap);
 
-    // Ask the rti to provide the attribute at index
-    void requestAttributeUpdate(unsigned index);
-    void requestAttributeUpdate();
-
     void registerInstance();
     void deleteInstance(const RTIData& tag);
-    void localDeleteInstance();
 
     class AttributeCallback : public SGReferenced {
     public:
@@ -85,11 +80,6 @@
     void updateAttributeValues(const RTIData& tag);
     void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag);
 
-    // Retrieve queued up updates up to and including timestamp,
-    // Note that this only applies to timestamped updates.
-    // The unordered updates are reflected as they arrive
-    void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp);
-
 private:
     void removeInstance(const RTIData& tag);
     void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);

Modified: simgear/trunk/simgear/hla/HLAPropertyDataElement.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAPropertyDataElement.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAPropertyDataElement.cxx (original)
+++ simgear/trunk/simgear/hla/HLAPropertyDataElement.cxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -17,230 +17,489 @@
 
 #include "HLAPropertyDataElement.hxx"
 
+#include "HLAArrayDataElement.hxx"
+#include "HLABasicDataElement.hxx"
+#include "HLADataElementVisitor.hxx"
 #include "HLADataTypeVisitor.hxx"
+#include "HLAFixedRecordDataElement.hxx"
+#include "HLAVariantDataElement.hxx"
 
 namespace simgear {
 
-class HLAPropertyDataElement::DecodeVisitor : public HLADataTypeDecodeVisitor {
+class HLAPropertyDataElement::ScalarDecodeVisitor : public HLADataTypeDecodeVisitor {
 public:
-    DecodeVisitor(HLADecodeStream& stream, HLAPropertyReference& propertyReference) :
+    ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
         HLADataTypeDecodeVisitor(stream),
-        _propertyReference(propertyReference)
+        _propertyNode(propertyNode)
     { }
+    virtual ~ScalarDecodeVisitor()
+    { }
 
     virtual void apply(const HLAInt8DataType& dataType)
     {
         int8_t value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setIntValue(value);
+        _propertyNode.setIntValue(value);
     }
     virtual void apply(const HLAUInt8DataType& dataType)
     {
         uint8_t value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setIntValue(value);
+        _propertyNode.setIntValue(value);
     }
     virtual void apply(const HLAInt16DataType& dataType)
     {
         int16_t value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setIntValue(value);
+        _propertyNode.setIntValue(value);
     }
     virtual void apply(const HLAUInt16DataType& dataType)
     {
         uint16_t value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setIntValue(value);
+        _propertyNode.setIntValue(value);
     }
     virtual void apply(const HLAInt32DataType& dataType)
     {
         int32_t value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setIntValue(value);
+        _propertyNode.setIntValue(value);
     }
     virtual void apply(const HLAUInt32DataType& dataType)
     {
         uint32_t value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setIntValue(value);
+        _propertyNode.setIntValue(value);
     }
     virtual void apply(const HLAInt64DataType& dataType)
     {
         int64_t value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setLongValue(value);
+        _propertyNode.setLongValue(value);
     }
     virtual void apply(const HLAUInt64DataType& dataType)
     {
         uint64_t value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setLongValue(value);
+        _propertyNode.setLongValue(value);
     }
     virtual void apply(const HLAFloat32DataType& dataType)
     {
         float value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setFloatValue(value);
+        _propertyNode.setFloatValue(value);
     }
     virtual void apply(const HLAFloat64DataType& dataType)
     {
         double value = 0;
         dataType.decode(_stream, value);
-        _propertyReference.setDoubleValue(value);
-    }
+        _propertyNode.setDoubleValue(value);
+    }
+
+protected:
+    SGPropertyNode& _propertyNode;
+};
+
+class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
+public:
+    ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
+        HLADataTypeEncodeVisitor(stream),
+        _propertyNode(propertyNode)
+    { }
+    virtual ~ScalarEncodeVisitor()
+    { }
+
+    virtual void apply(const HLAInt8DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getIntValue());
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getIntValue());
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getIntValue());
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getIntValue());
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getIntValue());
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getIntValue());
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getLongValue());
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getLongValue());
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getFloatValue());
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        dataType.encode(_stream, _propertyNode.getDoubleValue());
+    }
+
+protected:
+    const SGPropertyNode& _propertyNode;
+};
+
+class HLAPropertyDataElement::ScalarDataElement : public HLABasicDataElement {
+public:
+    ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode);
+    virtual ~ScalarDataElement();
+
+    virtual bool encode(HLAEncodeStream& stream) const;
+    virtual bool decode(HLADecodeStream& stream);
+
+private:
+    SGSharedPtr<SGPropertyNode> _propertyNode;
+};
+
+HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) :
+    HLABasicDataElement(dataType),
+    _propertyNode(propertyNode)
+{
+}
+
+HLAPropertyDataElement::ScalarDataElement::~ScalarDataElement()
+{
+}
+
+bool
+HLAPropertyDataElement::ScalarDataElement::encode(HLAEncodeStream& stream) const
+{
+    ScalarEncodeVisitor visitor(stream, *_propertyNode);
+    _dataType->accept(visitor);
+    return true;
+}
+
+bool
+HLAPropertyDataElement::ScalarDataElement::decode(HLADecodeStream& stream)
+{
+    ScalarDecodeVisitor visitor(stream, *_propertyNode);
+    _dataType->accept(visitor);
+    return true;
+}
+
+class HLAPropertyDataElement::StringDataElement : public HLAStringDataElement {
+public:
+    StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode);
+    virtual ~StringDataElement();
+
+    virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
+
+    class Listener : public SGPropertyChangeListener {
+    public:
+        Listener(StringDataElement* stringDataElement);
+        virtual ~Listener();
+        virtual void valueChanged (SGPropertyNode * node);
+    private:
+        StringDataElement* _stringDataElement;
+    };
+
+private:
+    SGSharedPtr<SGPropertyNode> _propertyNode;
+    Listener* _listener;
+};
+
+HLAPropertyDataElement::StringDataElement::Listener::Listener(StringDataElement* stringDataElement) :
+            _stringDataElement(stringDataElement)
+{
+}
+
+HLAPropertyDataElement::StringDataElement::Listener::~Listener()
+{
+}
+
+void
+HLAPropertyDataElement::StringDataElement::Listener::valueChanged (SGPropertyNode * node)
+{
+    _stringDataElement->setValue(node->getStringValue());
+}
+
+HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) :
+    HLAStringDataElement(dataType),
+    _propertyNode(propertyNode),
+    _listener(new Listener(this))
+{
+    _propertyNode->addChangeListener(_listener, true);
+}
+
+HLAPropertyDataElement::StringDataElement::~StringDataElement()
+{
+    _propertyNode->removeChangeListener(_listener);
+    delete _listener;
+    _listener = 0;
+}
+
+bool
+HLAPropertyDataElement::StringDataElement::decodeElement(HLADecodeStream& stream, unsigned i)
+{
+    if (!HLAStringDataElement::decodeElement(stream, i))
+        return false;
+    if (i + 1 == getValue().size())
+        _propertyNode->setStringValue(getValue());
+    return true;
+}
+
+class HLAPropertyDataElement::DataElementFactoryVisitor : public HLADataTypeVisitor {
+public:
+    DataElementFactoryVisitor(SGPropertyNode* propertyNode) :
+        _propertyNode(propertyNode)
+    { }
+    virtual ~DataElementFactoryVisitor()
+    { }
+
+    virtual void apply(const HLADataType& dataType)
+    {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
+               << dataType.getName() << "\"");
+    }
+
+    virtual void apply(const HLAInt8DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAUInt8DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAInt16DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAUInt16DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAInt32DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAUInt32DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAInt64DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAUInt64DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAFloat32DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+    virtual void apply(const HLAFloat64DataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(&dataType, _propertyNode.get());
+    }
+
+    class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
+    public:
+        ArrayDataElementFactory(SGPropertyNode* propertyNode) :
+            _propertyNode(propertyNode)
+        { }
+        virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
+        {
+            const HLADataType* dataType = element.getElementDataType();
+            if (!dataType)
+                return 0;
+
+            SGPropertyNode* parent = _propertyNode->getParent();
+            DataElementFactoryVisitor visitor(parent->getChild(_propertyNode->getNameString(), index, true));
+            dataType->accept(visitor);
+            return visitor.getDataElement();
+        }
+    private:
+        SGSharedPtr<SGPropertyNode> _propertyNode;
+    };
 
     virtual void apply(const HLAFixedArrayDataType& dataType)
     {
-        unsigned numElements = dataType.getNumElements();
-        std::string value;
-        value.reserve(numElements);
-        for (unsigned i = 0; i < numElements; ++i) {
-            HLATemplateDecodeVisitor<char> visitor(_stream);
-            dataType.getElementDataType()->accept(visitor);
-            value.push_back(visitor.getValue());
-        }
-        _propertyReference.setStringValue(value);
-    }
+        if (dataType.getIsString()) {
+            _dataElement = new StringDataElement(&dataType, _propertyNode.get());
+        } else {
+            SGSharedPtr<HLAArrayDataElement> arrayDataElement;
+            arrayDataElement = new HLAArrayDataElement(&dataType);
+            arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
+            arrayDataElement->setNumElements(dataType.getNumElements());
+            _dataElement = arrayDataElement;
+        }
+    }
+
     virtual void apply(const HLAVariableArrayDataType& dataType)
     {
-        HLATemplateDecodeVisitor<unsigned> numElementsVisitor(_stream);
-        dataType.getSizeDataType()->accept(numElementsVisitor);
-        unsigned numElements = numElementsVisitor.getValue();
-        std::string value;
-        value.reserve(numElements);
-        for (unsigned i = 0; i < numElements; ++i) {
-            HLATemplateDecodeVisitor<char> visitor(_stream);
-            dataType.getElementDataType()->accept(visitor);
-            value.push_back(visitor.getValue());
-        }
-        _propertyReference.setStringValue(value);
-    }
-
-protected:
-    HLAPropertyReference& _propertyReference;
+        if (dataType.getIsString()) {
+            _dataElement = new StringDataElement(&dataType, _propertyNode.get());
+        } else {
+            SGSharedPtr<HLAArrayDataElement> arrayDataElement;
+            arrayDataElement = new HLAArrayDataElement(&dataType);
+            arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
+            _dataElement = arrayDataElement;
+        }
+    }
+
+    virtual void apply(const HLAEnumeratedDataType& dataType)
+    {
+        _dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
+    }
+
+    virtual void apply(const HLAFixedRecordDataType& dataType)
+    {
+        SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
+        recordDataElement = new HLAFixedRecordDataElement(&dataType);
+
+        unsigned numFields = dataType.getNumFields();
+        for (unsigned i = 0; i < numFields; ++i) {
+            DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType.getFieldName(i), 0, true));
+            dataType.getFieldDataType(i)->accept(visitor);
+            recordDataElement->setField(i, visitor._dataElement.get());
+        }
+
+        _dataElement = recordDataElement;
+    }
+
+    class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
+    public:
+        VariantDataElementFactory(SGPropertyNode* propertyNode) :
+            _propertyNode(propertyNode)
+        { }
+        virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
+        {
+            const HLAVariantDataType* dataType = element.getDataType();
+            if (!dataType)
+                return 0;
+            const HLADataType* alternativeDataType = element.getAlternativeDataType();
+            if (!alternativeDataType)
+                return 0;
+            DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType->getAlternativeName(index), 0, true));
+            alternativeDataType->accept(visitor);
+            return visitor.getDataElement();
+        }
+    private:
+        SGSharedPtr<SGPropertyNode> _propertyNode;
+    };
+
+    virtual void apply(const HLAVariantDataType& dataType)
+    {
+        SGSharedPtr<HLAVariantDataElement> variantDataElement;
+        variantDataElement = new HLAVariantDataElement(&dataType);
+        variantDataElement->setDataElementFactory(new VariantDataElementFactory(_propertyNode.get()));
+        _dataElement = variantDataElement;
+    }
+
+    HLADataElement* getDataElement()
+    { return _dataElement.release(); }
+
+private:
+    SGSharedPtr<SGPropertyNode> _propertyNode;
+    SGSharedPtr<HLADataElement> _dataElement;
 };
 
-class HLAPropertyDataElement::EncodeVisitor : public HLADataTypeEncodeVisitor {
-public:
-    EncodeVisitor(HLAEncodeStream& stream, const HLAPropertyReference& propertyReference) :
-        HLADataTypeEncodeVisitor(stream),
-        _propertyReference(propertyReference)
-    { }
-
-    virtual void apply(const HLAInt8DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getIntValue());
-    }
-    virtual void apply(const HLAUInt8DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getIntValue());
-    }
-    virtual void apply(const HLAInt16DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getIntValue());
-    }
-    virtual void apply(const HLAUInt16DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getIntValue());
-    }
-    virtual void apply(const HLAInt32DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getIntValue());
-    }
-    virtual void apply(const HLAUInt32DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getIntValue());
-    }
-    virtual void apply(const HLAInt64DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getLongValue());
-    }
-    virtual void apply(const HLAUInt64DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getLongValue());
-    }
-    virtual void apply(const HLAFloat32DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getFloatValue());
-    }
-    virtual void apply(const HLAFloat64DataType& dataType)
-    {
-        dataType.encode(_stream, _propertyReference.getDoubleValue());
-    }
-
-    virtual void apply(const HLAFixedArrayDataType& dataType)
-    {
-        unsigned numElements = dataType.getNumElements();
-        std::string value = _propertyReference.getStringValue();
-        for (unsigned i = 0; i < numElements; ++i) {
-            if (i < value.size()) {
-                HLATemplateEncodeVisitor<char> visitor(_stream, value[i]);
-                dataType.getElementDataType()->accept(visitor);
+HLAPropertyDataElement::HLAPropertyDataElement()
+{
+}
+
+HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode)
+{
+    setPropertyNode(propertyNode);
+}
+
+HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) :
+    _dataType(dataType)
+{
+    setPropertyNode(propertyNode);
+}
+
+HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) :
+    _dataType(dataType)
+{
+}
+
+HLAPropertyDataElement::~HLAPropertyDataElement()
+{
+}
+
+void
+HLAPropertyDataElement::accept(HLADataElementVisitor& visitor)
+{
+    if (_dataElement.valid()) {
+        visitor.apply(*_dataElement);
+    } else {
+        // We cant do anything if the data type is not valid
+        if (_dataType.valid()) {
+            HLADataElementFactoryVisitor factoryVisitor;
+            _dataType->accept(factoryVisitor);
+            _dataElement = factoryVisitor.getDataElement();
+            if (_dataElement.valid()) {
+                visitor.apply(*_dataElement);
             } else {
-                HLADataTypeEncodeVisitor visitor(_stream);
-                dataType.getElementDataType()->accept(visitor);
+                HLADataElement::accept(visitor);
             }
-        }
-    }
-
-    virtual void apply(const HLAVariableArrayDataType& dataType)
-    {
-        std::string value = _propertyReference.getStringValue();
-        HLATemplateEncodeVisitor<std::string::size_type> numElementsVisitor(_stream, value.size());
-        dataType.getSizeDataType()->accept(numElementsVisitor);
-        for (unsigned i = 0; i < value.size(); ++i) {
-            HLATemplateEncodeVisitor<char> visitor(_stream, value[i]);
-            dataType.getElementDataType()->accept(visitor);
-        }
-    }
-
-protected:
-    const HLAPropertyReference& _propertyReference;
-};
-
-HLAPropertyDataElement::HLAPropertyDataElement(HLAPropertyReference* propertyReference) :
-    _propertyReference(propertyReference)
-{
-}
-
-HLAPropertyDataElement::HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference) :
-    _dataType(dataType),
-    _propertyReference(propertyReference)
-{
-}
-
-HLAPropertyDataElement::~HLAPropertyDataElement()
-{
+        } else {
+            HLADataElement::accept(visitor);
+        }
+    }
+}
+
+void
+HLAPropertyDataElement::accept(HLAConstDataElementVisitor& visitor) const
+{
+    if (_dataElement.valid()) {
+        visitor.apply(*_dataElement);
+    } else {
+        HLADataElement::accept(visitor);
+    }
 }
 
 bool
 HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
 {
-    if (!_dataType.valid())
-        return false;
-    if (_propertyReference.valid()) {
-        EncodeVisitor visitor(stream, *_propertyReference);
-        _dataType->accept(visitor);
+    if (_dataElement.valid()) {
+        return _dataElement->encode(stream);
     } else {
+        if (!_dataType.valid())
+            return false;
         HLADataTypeEncodeVisitor visitor(stream);
         _dataType->accept(visitor);
-    }
-    return true;
+        return true;
+    }
 }
 
 bool
 HLAPropertyDataElement::decode(HLADecodeStream& stream)
 {
-    if (!_dataType.valid())
+    if (_dataElement.valid()) {
+        return _dataElement->decode(stream);
+    } else if (!_dataType.valid()) {
+        // We cant do anything if the data type is not valid
         return false;
-    if (_propertyReference.valid()) {
-        DecodeVisitor visitor(stream, *_propertyReference);
+    } else {
+        HLADataElementFactoryVisitor visitor;
         _dataType->accept(visitor);
-    } else {
-        HLADataTypeDecodeVisitor visitor(stream);
-        _dataType->accept(visitor);
-    }
-    return true;
+        _dataElement = visitor.getDataElement();
+        if (_dataElement.valid()) {
+            return _dataElement->decode(stream);
+        } else {
+            HLADataTypeDecodeVisitor visitor(stream);
+            _dataType->accept(visitor);
+            return true;
+        }
+    }
 }
 
 const HLADataType*
@@ -252,18 +511,52 @@
 bool
 HLAPropertyDataElement::setDataType(const HLADataType* dataType)
 {
-    if (dataType->toBasicDataType()) {
-        _dataType = dataType;
-        return true;
-    } else {
-        const HLAArrayDataType* arrayDataType = dataType->toArrayDataType();
-        if (arrayDataType && arrayDataType->getElementDataType() &&
-            arrayDataType->getElementDataType()->toBasicDataType()) {
-            _dataType = dataType;
-            return true;
-        }
-    }
-    return false;
+    _dataType = dataType;
+    if (_dataType.valid() && _propertyNode.valid())
+        _dataElement = createDataElement(_dataType, _propertyNode);
+    return true;
+}
+
+void
+HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode)
+{
+    _propertyNode = propertyNode;
+    if (_dataType.valid() && _propertyNode.valid())
+        _dataElement = createDataElement(_dataType, _propertyNode);
+}
+
+SGPropertyNode*
+HLAPropertyDataElement::getPropertyNode()
+{
+    return _propertyNode.get();
+}
+
+const SGPropertyNode*
+HLAPropertyDataElement::getPropertyNode() const
+{
+    return _propertyNode.get();
+}
+
+HLADataElement*
+HLAPropertyDataElement::createDataElement(const SGSharedPtr<const HLADataType>& dataType,
+                                          const SGSharedPtr<SGPropertyNode>& propertyNode)
+{
+    DataElementFactoryVisitor visitor(propertyNode);
+    dataType->accept(visitor);
+    SGSharedPtr<HLADataElement> dataElement = visitor.getDataElement();
+
+    // Copy over the content of the previous data element if there is any.
+    if (_dataElement.valid()) {
+        // FIXME is encode/decode the right tool here??
+        RTIData data;
+        HLAEncodeStream encodeStream(data);
+        if (_dataElement->encode(encodeStream)) {
+            HLADecodeStream decodeStream(data);
+            dataElement->decode(decodeStream);
+        }
+    }
+
+    return dataElement.release();
 }
 
 } // namespace simgear

Modified: simgear/trunk/simgear/hla/HLAPropertyDataElement.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAPropertyDataElement.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAPropertyDataElement.hxx (original)
+++ simgear/trunk/simgear/hla/HLAPropertyDataElement.hxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -18,140 +18,21 @@
 #ifndef HLAPropertyDataElement_hxx
 #define HLAPropertyDataElement_hxx
 
-#include <set>
 #include <simgear/props/props.hxx>
 #include "HLADataElement.hxx"
 
 namespace simgear {
 
-class HLAPropertyReference : public SGReferenced {
-public:
-    HLAPropertyReference()
-    { }
-    HLAPropertyReference(const std::string& relativePath) :
-        _relativePath(relativePath)
-    { }
-
-    void setIntValue(int value)
-    {
-        if (!_propertyNode.valid())
-            return;
-        _propertyNode->setIntValue(value);
-    }
-    int getIntValue() const
-    {
-        if (!_propertyNode.valid())
-            return 0;
-        return _propertyNode->getIntValue();
-    }
-
-    void setLongValue(long value)
-    {
-        if (!_propertyNode.valid())
-            return;
-        _propertyNode->setLongValue(value);
-    }
-    long getLongValue() const
-    {
-        if (!_propertyNode.valid())
-            return 0;
-        return _propertyNode->getLongValue();
-    }
-
-    void setFloatValue(float value)
-    {
-        if (!_propertyNode.valid())
-            return;
-        _propertyNode->setFloatValue(value);
-    }
-    float getFloatValue() const
-    {
-        if (!_propertyNode.valid())
-            return 0;
-        return _propertyNode->getFloatValue();
-    }
-
-    void setDoubleValue(double value)
-    {
-        if (!_propertyNode.valid())
-            return;
-        _propertyNode->setDoubleValue(value);
-    }
-    double getDoubleValue() const
-    {
-        if (!_propertyNode.valid())
-            return 0;
-        return _propertyNode->getDoubleValue();
-    }
-
-    void setStringValue(const std::string& value)
-    {
-        if (!_propertyNode.valid())
-            return;
-        _propertyNode->setStringValue(value);
-    }
-    std::string getStringValue() const
-    {
-        if (!_propertyNode.valid())
-            return std::string();
-        return _propertyNode->getStringValue();
-    }
-
-    SGPropertyNode* getPropertyNode()
-    { return _propertyNode.get(); }
-
-    void setRootNode(SGPropertyNode* rootNode)
-    {
-        if (!rootNode)
-            _propertyNode.clear();
-        else
-            _propertyNode = rootNode->getNode(_relativePath, true);
-    }
-
-private:
-    std::string _relativePath;
-    SGSharedPtr<SGPropertyNode> _propertyNode;
-};
-
-class HLAPropertyReferenceSet : public SGReferenced {
-public:
-    void insert(const SGSharedPtr<HLAPropertyReference>& propertyReference)
-    {
-        _propertyReferenceSet.insert(propertyReference);
-        propertyReference->setRootNode(_rootNode.get());
-    }
-    void remove(const SGSharedPtr<HLAPropertyReference>& propertyReference)
-    {
-        PropertyReferenceSet::iterator i = _propertyReferenceSet.find(propertyReference);
-        if (i == _propertyReferenceSet.end())
-            return;
-        _propertyReferenceSet.erase(i);
-        propertyReference->setRootNode(0);
-    }
-
-    void setRootNode(SGPropertyNode* rootNode)
-    {
-        _rootNode = rootNode;
-        for (PropertyReferenceSet::iterator i = _propertyReferenceSet.begin();
-             i != _propertyReferenceSet.end(); ++i) {
-            (*i)->setRootNode(_rootNode.get());
-        }
-    }
-    SGPropertyNode* getRootNode()
-    { return _rootNode.get(); }
-
-private:
-    SGSharedPtr<SGPropertyNode> _rootNode;
-
-    typedef std::set<SGSharedPtr<HLAPropertyReference> > PropertyReferenceSet;
-    PropertyReferenceSet _propertyReferenceSet;
-};
-
 class HLAPropertyDataElement : public HLADataElement {
 public:
-    HLAPropertyDataElement(HLAPropertyReference* propertyReference);
-    HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference);
-    ~HLAPropertyDataElement();
+    HLAPropertyDataElement();
+    HLAPropertyDataElement(SGPropertyNode* propertyNode);
+    HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode);
+    HLAPropertyDataElement(const HLADataType* dataType);
+    virtual ~HLAPropertyDataElement();
+
+    virtual void accept(HLADataElementVisitor& visitor);
+    virtual void accept(HLAConstDataElementVisitor& visitor) const;
 
     virtual bool encode(HLAEncodeStream& stream) const;
     virtual bool decode(HLADecodeStream& stream);
@@ -159,12 +40,25 @@
     virtual const HLADataType* getDataType() const;
     virtual bool setDataType(const HLADataType* dataType);
 
+    void setPropertyNode(SGPropertyNode* propertyNode);
+    SGPropertyNode* getPropertyNode();
+    const SGPropertyNode* getPropertyNode() const;
+    
 private:
-    class DecodeVisitor;
-    class EncodeVisitor;
+    HLADataElement*
+    createDataElement(const SGSharedPtr<const HLADataType>& dataType, const SGSharedPtr<SGPropertyNode>& propertyNode);
+    
+    class ScalarDecodeVisitor;
+    class ScalarEncodeVisitor;
+    class ScalarDataElement;
+    class StringDecodeVisitor;
+    class StringEncodeVisitor;
+    class StringDataElement;
+    class DataElementFactoryVisitor;
 
     SGSharedPtr<const HLADataType> _dataType;
-    SGSharedPtr<HLAPropertyReference> _propertyReference;
+    SGSharedPtr<HLADataElement> _dataElement;
+    SGSharedPtr<SGPropertyNode> _propertyNode;
 };
 
 } // namespace simgear

Modified: simgear/trunk/simgear/hla/HLAVariantDataElement.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAVariantDataElement.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAVariantDataElement.cxx (original)
+++ simgear/trunk/simgear/hla/HLAVariantDataElement.cxx Sun Jul 15 09:07:01 2012
@@ -19,6 +19,8 @@
 
 #include <simgear/debug/logstream.hxx>
 
+#include "HLADataElementVisitor.hxx"
+
 namespace simgear {
 
 HLAAbstractVariantDataElement::HLAAbstractVariantDataElement(const HLAVariantDataType* dataType) :
@@ -28,6 +30,18 @@
 
 HLAAbstractVariantDataElement::~HLAAbstractVariantDataElement()
 {
+}
+
+void
+HLAAbstractVariantDataElement::accept(HLADataElementVisitor& visitor)
+{
+    visitor.apply(*this);
+}
+
+void
+HLAAbstractVariantDataElement::accept(HLAConstDataElementVisitor& visitor) const
+{
+    visitor.apply(*this);
 }
 
 bool

Modified: simgear/trunk/simgear/hla/HLAVariantDataElement.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/HLAVariantDataElement.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/HLAVariantDataElement.hxx (original)
+++ simgear/trunk/simgear/hla/HLAVariantDataElement.hxx Sun Jul 15 09:07:01 2012
@@ -29,6 +29,9 @@
 public:
     HLAAbstractVariantDataElement(const HLAVariantDataType* dataType);
     virtual ~HLAAbstractVariantDataElement();
+
+    virtual void accept(HLADataElementVisitor& visitor);
+    virtual void accept(HLAConstDataElementVisitor& visitor) const;
 
     virtual bool decode(HLADecodeStream& stream);
     virtual bool encode(HLAEncodeStream& stream) const;

Modified: simgear/trunk/simgear/hla/RTI13Ambassador.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTI13Ambassador.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTI13Ambassador.hxx (original)
+++ simgear/trunk/simgear/hla/RTI13Ambassador.hxx Sun Jul 15 09:07:01 2012
@@ -15,8 +15,8 @@
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 
-#ifndef RTIAmbassador_hxx
-#define RTIAmbassador_hxx
+#ifndef RTI13Ambassador_hxx
+#define RTI13Ambassador_hxx
 
 #include <cstdlib>
 #include <list>
@@ -45,58 +45,20 @@
 
 namespace simgear {
 
-class RTI13Ambassador : public SGWeakReferenced {
+class RTI13Federate;
+
+class RTI13Ambassador : public SGReferenced {
 public:
-    RTI13Ambassador() :
-        _federateAmbassador(*this),
-        _timeRegulationEnabled(false),
-        _timeConstrainedEnabled(false),
-        _timeAdvancePending(false)
+    ~RTI13Ambassador()
     { }
-    virtual ~RTI13Ambassador()
-    { }
-
-    // processes the queues that filled up during the past
-    void processQueues()
-    {
-        while (!_queueCallbackList.empty()) {
-            (*_queueCallbackList.front())();
-            _queueCallbackList.pop_front();
-        }
-
-        while (!_objectInstancePendingCallbackList.empty()) {
-            (*_objectInstancePendingCallbackList.begin())->flushPendingRequests();
-            _objectInstancePendingCallbackList.erase(_objectInstancePendingCallbackList.begin());
-        }
-    }
-
-    bool getTimeRegulationEnabled() const
-    { return _timeRegulationEnabled; }
-    bool getTimeConstrainedEnabled() const
-    { return _timeConstrainedEnabled; }
-    bool getTimeAdvancePending() const
-    { return _timeAdvancePending; }
-    const SGTimeStamp& getCurrentLogicalTime() const
-    { return _federateTime; }
-
-    bool getFederationSynchronizationPointAnnounced(const std::string& label)
-    { return _pendingSyncLabels.find(label) != _pendingSyncLabels.end(); }
-    bool getFederationSynchronized(const std::string& label)
-    {
-        std::set<std::string>::iterator i = _syncronizedSyncLabels.find(label);
-        if (i == _syncronizedSyncLabels.end())
-            return false;
-        _syncronizedSyncLabels.erase(i);
-        return true;
-    }
 
     void createFederationExecution(const std::string& name, const std::string& objectModel)
     { _rtiAmbassador.createFederationExecution(name.c_str(), objectModel.c_str()); }
     void destroyFederationExecution(const std::string& name)
     { _rtiAmbassador.destroyFederationExecution(name.c_str()); }
 
-    RTI::FederateHandle joinFederationExecution(const std::string& federate, const std::string& federation)
-    { return _rtiAmbassador.joinFederationExecution(federate.c_str(), federation.c_str(), &_federateAmbassador); }
+    RTI::FederateHandle joinFederationExecution(const std::string& federate, const std::string& federation, RTI::FederateAmbassador* federateAmbassador)
+    { return _rtiAmbassador.joinFederationExecution(federate.c_str(), federation.c_str(), federateAmbassador); }
     void resignFederationExecution()
     { _rtiAmbassador.resignFederationExecution(RTI::DELETE_OBJECTS_AND_RELEASE_ATTRIBUTES); }
 
@@ -114,13 +76,8 @@
     void unsubscribeObjectClass(const RTI::ObjectClassHandle& handle)
     { _rtiAmbassador.unsubscribeObjectClass(handle); }
 
-    RTI13ObjectInstance* registerObjectInstance(const RTI13ObjectClass* objectClass, HLAObjectInstance* hlaObjectInstance)
-    {
-        RTI::ObjectHandle objectHandle = _rtiAmbassador.registerObjectInstance(objectClass->getHandle());
-        RTI13ObjectInstance* objectInstance = new RTI13ObjectInstance(objectHandle, hlaObjectInstance, objectClass, this, true);
-        _objectInstanceMap[objectHandle] = objectInstance;
-        return objectInstance;
-    }
+    RTI::ObjectHandle registerObjectInstance(const RTI::ObjectClassHandle& handle)
+    { return _rtiAmbassador.registerObjectInstance(handle); }
     void updateAttributeValues(const RTI::ObjectHandle& objectHandle, const RTI::AttributeHandleValuePairSet& attributeValues,
                                const SGTimeStamp& timeStamp, const RTIData& tag)
     { _rtiAmbassador.updateAttributeValues(objectHandle, attributeValues, toFedTime(timeStamp), tag.data()); }
@@ -133,38 +90,11 @@
     // { _rtiAmbassador.sendInteraction(interactionClassHandle, parameters, tag.data()); }
 
     void deleteObjectInstance(const RTI::ObjectHandle& objectHandle, const SGTimeStamp& timeStamp, const RTIData& tag)
-    {
-        RTI::EventRetractionHandle h = _rtiAmbassador.deleteObjectInstance(objectHandle, toFedTime(timeStamp), tag.data());
-        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
-        if (i == _objectInstanceMap.end()) {
-            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found.");
-            return;
-        }
-        _objectInstancePendingCallbackList.erase(i->second);
-        _objectInstanceMap.erase(i);
-    }
+    { /* RTI::EventRetractionHandle h = */ _rtiAmbassador.deleteObjectInstance(objectHandle, toFedTime(timeStamp), tag.data()); }
     void deleteObjectInstance(const RTI::ObjectHandle& objectHandle, const RTIData& tag)
-    {
-        _rtiAmbassador.deleteObjectInstance(objectHandle, tag.data());
-        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
-        if (i == _objectInstanceMap.end()) {
-            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found.");
-            return;
-        }
-        _objectInstancePendingCallbackList.erase(i->second);
-        _objectInstanceMap.erase(i);
-    }
+    { _rtiAmbassador.deleteObjectInstance(objectHandle, tag.data()); }
     void localDeleteObjectInstance(const RTI::ObjectHandle& objectHandle)
-    {
-        _rtiAmbassador.localDeleteObjectInstance(objectHandle);
-        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
-        if (i == _objectInstanceMap.end()) {
-            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found.");
-            return;
-        }
-        _objectInstancePendingCallbackList.erase(i->second);
-        _objectInstanceMap.erase(i);
-    }
+    { _rtiAmbassador.localDeleteObjectInstance(objectHandle); }
 
     void requestObjectAttributeValueUpdate(const RTI::ObjectHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet)
     { _rtiAmbassador.requestObjectAttributeValueUpdate(handle, attributeHandleSet); }
@@ -351,81 +281,62 @@
 
     /// Time Management
 
-    void enableTimeRegulation(const SGTimeStamp& federateTime, const SGTimeStamp& lookahead)
-    { _rtiAmbassador.enableTimeRegulation(toFedTime(federateTime), toFedTime(lookahead)); }
+    void enableTimeRegulation(const SGTimeStamp& lookahead)
+    {
+        RTIfedTime federateTime;
+        federateTime.setZero();
+        _rtiAmbassador.enableTimeRegulation(federateTime, toFedTime(lookahead));
+    }
     void disableTimeRegulation()
-    { _rtiAmbassador.disableTimeRegulation(); _timeRegulationEnabled = false; }
+    { _rtiAmbassador.disableTimeRegulation();}
 
     void enableTimeConstrained()
     { _rtiAmbassador.enableTimeConstrained(); }
     void disableTimeConstrained()
-    { _rtiAmbassador.disableTimeConstrained(); _timeConstrainedEnabled = false; }
+    { _rtiAmbassador.disableTimeConstrained(); }
 
     void timeAdvanceRequest(const SGTimeStamp& time)
-    { _rtiAmbassador.timeAdvanceRequest(toFedTime(time)); _timeAdvancePending = true; }
+    { _rtiAmbassador.timeAdvanceRequest(toFedTime(time)); }
     void timeAdvanceRequestAvailable(const SGTimeStamp& time)
-    { _rtiAmbassador.timeAdvanceRequestAvailable(toFedTime(time)); _timeAdvancePending = true; }
-
-    // bool queryLBTS(double& time)
-    // {
-    //     try {
-    //         RTIfedTime fedTime;
-    //         _rtiAmbassador.queryLBTS(fedTime);
-    //         time = fedTime.getTime();
-    //         return true;
-    //     } catch (RTI::FederateNotExecutionMember& e) {
-    //     } catch (RTI::ConcurrentAccessAttempted& e) {
-    //     } catch (RTI::SaveInProgress& e) {
-    //     } catch (RTI::RestoreInProgress& e) {
-    //     } catch (RTI::RTIinternalError& e) {
-    //     }
-    //     return false;
-    // }
-    // bool queryFederateTime(double& time)
-    // {
-    //     try {
-    //         RTIfedTime fedTime;
-    //         _rtiAmbassador.queryFederateTime(fedTime);
-    //         time = fedTime.getTime();
-    //         return true;
-    //     } catch (RTI::FederateNotExecutionMember& e) {
-    //     } catch (RTI::ConcurrentAccessAttempted& e) {
-    //     } catch (RTI::SaveInProgress& e) {
-    //     } catch (RTI::RestoreInProgress& e) {
-    //     } catch (RTI::RTIinternalError& e) {
-    //     }
-    //     return false;
-    // }
-
-    // bool queryLookahead(double& time)
-    // {
-    //     try {
-    //         RTIfedTime fedTime;
-    //         _rtiAmbassador.queryLookahead(fedTime);
-    //         time = fedTime.getTime();
-    //         return true;
-    //     } catch (RTI::FederateNotExecutionMember& e) {
-    //     } catch (RTI::ConcurrentAccessAttempted& e) {
-    //     } catch (RTI::SaveInProgress& e) {
-    //     } catch (RTI::RestoreInProgress& e) {
-    //     } catch (RTI::RTIinternalError& e) {
-    //     }
-    //     return false;
-    // }
-
-    RTI13ObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass)
-    {
-        RTI::ObjectClassHandle objectClassHandle;
-        objectClassHandle = getObjectClassHandle(name);
-        if (_objectClassMap.find(objectClassHandle) != _objectClassMap.end()) {
-            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create object class, object class already exists!");
-            return 0;
-        }
-        RTI13ObjectClass* rtiObjectClass;
-        rtiObjectClass = new RTI13ObjectClass(hlaObjectClass, objectClassHandle, this);
-        _objectClassMap[objectClassHandle] = rtiObjectClass;
-        return rtiObjectClass;
-    }
+    { _rtiAmbassador.timeAdvanceRequestAvailable(toFedTime(time)); }
+    void flushQueueRequest(const SGTimeStamp& time)
+    { _rtiAmbassador.flushQueueRequest(toFedTime(time)); }
+
+    bool queryGALT(SGTimeStamp& timeStamp)
+    {
+        RTIfedTime fedTime;
+        fedTime.setPositiveInfinity();
+        _rtiAmbassador.queryLBTS(fedTime);
+        if (fedTime.isPositiveInfinity())
+            return false;
+        timeStamp = toTimeStamp(fedTime);
+        return true;
+    }
+    bool queryLITS(SGTimeStamp& timeStamp)
+    {
+        RTIfedTime fedTime;
+        fedTime.setPositiveInfinity();
+        _rtiAmbassador.queryMinNextEventTime(fedTime);
+        if (fedTime.isPositiveInfinity())
+            return false;
+        timeStamp = toTimeStamp(fedTime);
+        return true;
+    }
+    void queryFederateTime(SGTimeStamp& timeStamp)
+    {
+        RTIfedTime fedTime;
+        _rtiAmbassador.queryFederateTime(fedTime);
+        timeStamp = toTimeStamp(fedTime);
+    }
+    void modifyLookahead(const SGTimeStamp& timeStamp)
+    { _rtiAmbassador.modifyLookahead(toFedTime(timeStamp)); }
+    void queryLookahead(SGTimeStamp& timeStamp)
+    {
+        RTIfedTime fedTime;
+        _rtiAmbassador.queryLookahead(fedTime);
+        timeStamp = toTimeStamp(fedTime);
+    }
+
     RTI::ObjectClassHandle getObjectClassHandle(const std::string& name)
     { return _rtiAmbassador.getObjectClassHandle(name.c_str()); }
     std::string getObjectClassName(const RTI::ObjectClassHandle& handle)
@@ -486,17 +397,6 @@
     //     return parameterName;
     // }
 
-    RTI13ObjectInstance* getObjectInstance(const std::string& name)
-    {
-        RTI::ObjectHandle objectHandle;
-        objectHandle = getObjectInstanceHandle(name);
-        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
-        if (i == _objectInstanceMap.end()) {
-            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found.");
-            return 0;
-        }
-        return i->second;
-    }
     RTI::ObjectHandle getObjectInstanceHandle(const std::string& name)
     { return _rtiAmbassador.getObjectInstanceHandle(name.c_str()); }
     std::string getObjectInstanceName(const RTI::ObjectHandle& objectHandle)
@@ -552,498 +452,6 @@
     bool tick(double minimum, double maximum)
     { return _rtiAmbassador.tick(minimum, maximum); }
 
-    void addObjectInstanceForCallback(RTIObjectInstance* objectIntance)
-    { _objectInstancePendingCallbackList.insert(objectIntance); }
-
-private:
-    /// Generic callback to execute some notification on objects in a way that they are not prone to
-    /// ConcurrentAccess exceptions.
-    class QueueCallback : public SGReferenced {
-    public:
-        virtual ~QueueCallback() {}
-        virtual void operator()() = 0;
-    };
-
-    class RemoveObjectCallback : public QueueCallback {
-    public:
-        RemoveObjectCallback(SGSharedPtr<RTIObjectInstance> objectInstance, const RTIData& tag) :
-            _objectInstance(objectInstance),
-            _tag(tag)
-        { }
-        virtual void operator()()
-        {
-            _objectInstance->removeInstance(_tag);
-        }
-    private:
-        SGSharedPtr<RTIObjectInstance> _objectInstance;
-        RTIData _tag;
-    };
-
-    /// Just the interface class doing the callbacks into the parent class
-    struct FederateAmbassador : public RTI::FederateAmbassador {
-        FederateAmbassador(RTI13Ambassador& rtiAmbassador) :
-            _rtiAmbassador(rtiAmbassador)
-        {
-        }
-        virtual ~FederateAmbassador()
-        throw (RTI::FederateInternalError)
-        {
-        }
-
-        /// RTI federate ambassador callback functions.
-        virtual void synchronizationPointRegistrationSucceeded(const char* label)
-            throw (RTI::FederateInternalError)
-        {
-        }
-
-        virtual void synchronizationPointRegistrationFailed(const char* label)
-            throw (RTI::FederateInternalError)
-        {
-        }
-
-        virtual void announceSynchronizationPoint(const char* label, const char* tag)
-            throw (RTI::FederateInternalError)
-        {
-            _rtiAmbassador._pendingSyncLabels.insert(toStdString(label));
-        }
-
-        virtual void federationSynchronized(const char* label)
-            throw (RTI::FederateInternalError)
-        {
-            std::string s = toStdString(label);
-            _rtiAmbassador._pendingSyncLabels.erase(s);
-            _rtiAmbassador._syncronizedSyncLabels.insert(s);
-        }
-
-        virtual void initiateFederateSave(const char* label)
-            throw (RTI::UnableToPerformSave,
-                   RTI::FederateInternalError)
-        {
-        }
-
-        virtual void federationSaved()
-            throw (RTI::FederateInternalError)
-        {
-        }
-
-        virtual void federationNotSaved()
-            throw (RTI::FederateInternalError)
-        {
-        }
-
-        virtual void requestFederationRestoreSucceeded(const char* label)
-            throw (RTI::FederateInternalError)
-        {
-        }
-
-        virtual void requestFederationRestoreFailed(const char* label, const char* reason)
-            throw (RTI::FederateInternalError)
-        {
-        }
-
-        virtual void federationRestoreBegun()
-            throw (RTI::FederateInternalError)
-        {
-        }
-
-        virtual void initiateFederateRestore(const char* label, RTI::FederateHandle federateHandle)
-            throw (RTI::SpecifiedSaveLabelDoesNotExist,
-                   RTI::CouldNotRestore,
-                   RTI::FederateInternalError)
-        {
-        }
-
-        virtual void federationRestored()
-            throw (RTI::FederateInternalError)
-        {
-        }
-
-        virtual void federationNotRestored()
-            throw (RTI::FederateInternalError)
-        {
-        }
-
-        // Declaration Management
-        virtual void startRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle)
-            throw (RTI::ObjectClassNotPublished,
-                   RTI::FederateInternalError)
-        {
-            ObjectClassMap::iterator i = _rtiAmbassador._objectClassMap.find(objectClassHandle);
-            if (i == _rtiAmbassador._objectClassMap.end())
-                return;
-            if (!i->second.valid())
-                return;
-            i->second->startRegistration();
-        }
-
-        virtual void stopRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle)
-            throw (RTI::ObjectClassNotPublished,
-                   RTI::FederateInternalError)
-        {
-            ObjectClassMap::iterator i = _rtiAmbassador._objectClassMap.find(objectClassHandle);
-            if (i == _rtiAmbassador._objectClassMap.end())
-                return;
-            if (!i->second.valid())
-                return;
-            i->second->stopRegistration();
-        }
-
-        virtual void turnInteractionsOn(RTI::InteractionClassHandle interactionClassHandle)
-            throw (RTI::InteractionClassNotPublished,
-                   RTI::FederateInternalError)
-        {
-        }
-
-        virtual void turnInteractionsOff(RTI::InteractionClassHandle interactionClassHandle)
-            throw (RTI::InteractionClassNotPublished,
-                   RTI::FederateInternalError)
-        {
-        }
-
-
-        // Object Management
-        virtual void discoverObjectInstance(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const char* tag)
-            throw (RTI::CouldNotDiscover,
-                   RTI::ObjectClassNotKnown,
-                   RTI::FederateInternalError)
-        {
-            ObjectClassMap::iterator i = _rtiAmbassador._objectClassMap.find(objectClassHandle);
-            if (i == _rtiAmbassador._objectClassMap.end())
-                throw RTI::ObjectClassNotKnown("Federate: discoverObjectInstance()!");
-            if (!i->second.valid())
-                return;
-            SGSharedPtr<RTI13ObjectInstance> objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, &_rtiAmbassador, false);
-            _rtiAmbassador._objectInstanceMap[objectHandle] = objectInstance;
-            _rtiAmbassador._objectInstancePendingCallbackList.insert(objectInstance);
-            i->second->discoverInstance(objectInstance.get(), tagToData(tag));
-        }
-
-        virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet,
-                                            const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::FederateOwnsAttributes,
-                   RTI::InvalidFederationTime,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("Reflect attributes for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->reflectAttributeValues(attributeValuePairSet, toTimeStamp(fedTime), tagToData(tag));
-        }
-
-        virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet,
-                                            const char* tag)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::FederateOwnsAttributes,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("Reflect attributes for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->reflectAttributeValues(attributeValuePairSet, tagToData(tag));
-        }
-
-        virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters,
-                                        const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
-            throw (RTI::InteractionClassNotKnown,
-                   RTI::InteractionParameterNotKnown,
-                   RTI::InvalidFederationTime,
-                   RTI::FederateInternalError)
-        {
-        }
-
-        virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle,
-                                        const RTI::ParameterHandleValuePairSet& parameters, const char* tag)
-            throw (RTI::InteractionClassNotKnown,
-                   RTI::InteractionParameterNotKnown,
-                   RTI::FederateInternalError)
-        {
-        }
-
-        virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const RTI::FedTime& fedTime,
-                                          const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
-            throw (RTI::ObjectNotKnown,
-                   RTI::InvalidFederationTime,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!");
-            if (i->second.valid())
-                _rtiAmbassador._queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag)));
-            _rtiAmbassador._objectInstancePendingCallbackList.erase(i->second);
-            _rtiAmbassador._objectInstanceMap.erase(i);
-        }
-
-        virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const char* tag)
-            throw (RTI::ObjectNotKnown,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!");
-            if (i->second.valid())
-                _rtiAmbassador._queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag)));
-            _rtiAmbassador._objectInstancePendingCallbackList.erase(i->second);
-            _rtiAmbassador._objectInstanceMap.erase(i);
-        }
-
-        virtual void attributesInScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("Attributes in scope for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->attributesInScope(attributes);
-        }
-
-        virtual void attributesOutOfScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("Attributes in scope for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->attributesOutOfScope(attributes);
-        }
-
-        virtual void provideAttributeValueUpdate(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::AttributeNotOwned,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("Reflect attributes for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->provideAttributeValueUpdate(attributes);
-        }
-
-        virtual void turnUpdatesOnForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotOwned,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("Turn on attributes for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->turnUpdatesOnForObjectInstance(attributes);
-        }
-
-        virtual void turnUpdatesOffForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotOwned,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("Turn off attributes for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->turnUpdatesOffForObjectInstance(attributes);
-        }
-
-        // Ownership Management
-        virtual void requestAttributeOwnershipAssumption(RTI::ObjectHandle objectHandle,
-                                                         const RTI::AttributeHandleSet& attributes, const char* tag)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::AttributeAlreadyOwned,
-                   RTI::AttributeNotPublished,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("requestAttributeOwnershipAssumption for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->requestAttributeOwnershipAssumption(attributes, tagToData(tag));
-        }
-
-        virtual void attributeOwnershipDivestitureNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::AttributeNotOwned,
-                   RTI::AttributeDivestitureWasNotRequested,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("attributeOwnershipDivestitureNotification for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->attributeOwnershipDivestitureNotification(attributes);
-        }
-
-        virtual void attributeOwnershipAcquisitionNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::AttributeAcquisitionWasNotRequested,
-                   RTI::AttributeAlreadyOwned,
-                   RTI::AttributeNotPublished,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("attributeOwnershipAcquisitionNotification for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->attributeOwnershipAcquisitionNotification(attributes);
-        }
-
-        virtual void attributeOwnershipUnavailable(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::AttributeAlreadyOwned,
-                   RTI::AttributeAcquisitionWasNotRequested,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("attributeOwnershipUnavailable for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->attributeOwnershipUnavailable(attributes);
-        }
-
-        virtual void requestAttributeOwnershipRelease(RTI::ObjectHandle objectHandle,
-                                                      const RTI::AttributeHandleSet& attributes, const char* tag)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::AttributeNotOwned,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("requestAttributeOwnershipRelease for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->requestAttributeOwnershipRelease(attributes, tagToData(tag));
-        }
-
-        virtual void confirmAttributeOwnershipAcquisitionCancellation(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::AttributeAlreadyOwned,
-                   RTI::AttributeAcquisitionWasNotCanceled,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("confirmAttributeOwnershipAcquisitionCancellation for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->confirmAttributeOwnershipAcquisitionCancellation(attributes);
-        }
-
-        virtual void informAttributeOwnership(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle,
-                                              RTI::FederateHandle federateHandle)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("informAttributeOwnership for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->informAttributeOwnership(attributeHandle, federateHandle);
-        }
-
-        virtual void attributeIsNotOwned(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("attributeIsNotOwned for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->attributeIsNotOwned(attributeHandle);
-        }
-
-        virtual void attributeOwnedByRTI(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
-            throw (RTI::ObjectNotKnown,
-                   RTI::AttributeNotKnown,
-                   RTI::FederateInternalError)
-        {
-            ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle);
-            if (i == _rtiAmbassador._objectInstanceMap.end())
-                throw RTI::ObjectNotKnown("attributeOwnedByRTI for unknown object!");
-            if (!i->second.valid())
-                return;
-            i->second->attributeOwnedByRTI(attributeHandle);
-        }
-
-        // Time Management
-        virtual void timeRegulationEnabled(const RTI::FedTime& fedTime)
-            throw (RTI::InvalidFederationTime,
-                   RTI::EnableTimeRegulationWasNotPending,
-                   RTI::FederateInternalError)
-        {
-            _rtiAmbassador._timeRegulationEnabled = true;
-            _rtiAmbassador._federateTime = toTimeStamp(fedTime);
-            SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeRegulationEnabled: " << _rtiAmbassador._federateTime);
-        }
-
-        virtual void timeConstrainedEnabled(const RTI::FedTime& fedTime)
-            throw (RTI::InvalidFederationTime,
-                   RTI::EnableTimeConstrainedWasNotPending,
-                   RTI::FederateInternalError)
-        {
-            _rtiAmbassador._timeConstrainedEnabled = true;
-            _rtiAmbassador._federateTime = toTimeStamp(fedTime);
-            SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeConstrainedEnabled: " << _rtiAmbassador._federateTime);
-        }
-
-        virtual void timeAdvanceGrant(const RTI::FedTime& fedTime)
-            throw (RTI::InvalidFederationTime,
-                   RTI::TimeAdvanceWasNotInProgress,
-                   RTI::FederateInternalError)
-        {
-            _rtiAmbassador._federateTime = toTimeStamp(fedTime);
-            _rtiAmbassador._timeAdvancePending = false;
-            SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeAdvanceGrant: " << _rtiAmbassador._federateTime);
-        }
-
-        virtual void requestRetraction(RTI::EventRetractionHandle eventRetractionHandle)
-            throw (RTI::EventNotKnown,
-                   RTI::FederateInternalError)
-        {
-            // No retraction concept yet
-        }
-
-    private:
-        const RTIData& tagToData(const char* tag)
-        {
-            if (tag)
-                _cachedTag.setData(tag, std::strlen(tag) + 1);
-            else
-                _cachedTag.setData("", 1);
-            return _cachedTag;
-        }
-        RTIData _cachedTag;
-
-        RTI13Ambassador& _rtiAmbassador;
-    };
 
     static SGTimeStamp toTimeStamp(const RTI::FedTime& fedTime)
     {
@@ -1069,45 +477,9 @@
         return s;
     }
 
-    static std::string toStdString(const char* n)
-    {
-        if (!n)
-            return std::string();
-        return std::string(n);
-    }
-
     // The connection class
     RTI::RTIambassador _rtiAmbassador;
-
-    // The class with all the callbacks.
-    FederateAmbassador _federateAmbassador;
-
-    // All the sync labels we got an announcement for
-    std::set<std::string> _pendingSyncLabels;
-    std::set<std::string> _syncronizedSyncLabels;
-
-    // All that calls back into user code is just queued.
-    // That is to make sure we do not call recursively into the RTI
-    typedef std::list<SGSharedPtr<QueueCallback> > QueueCallbackList;
-    QueueCallbackList _queueCallbackList;
-    // All object instances that need to be called due to some event are noted here
-    // That is to make sure we do not call recursively into the RTI
-    typedef std::set<SGSharedPtr<RTIObjectInstance> > ObjectInstanceSet;
-    ObjectInstanceSet _objectInstancePendingCallbackList;
-
-    // Top level information for dispatching federate object attribute updates
-    typedef std::map<RTI::ObjectHandle, SGSharedPtr<RTI13ObjectInstance> > ObjectInstanceMap;
-    // Map of all available objects
-    ObjectInstanceMap _objectInstanceMap;
-
-    // Top level information for dispatching creation of federate objects
-    typedef std::map<RTI::ObjectClassHandle, SGSharedPtr<RTI13ObjectClass> > ObjectClassMap;
-    ObjectClassMap _objectClassMap;
-
-    bool _timeRegulationEnabled;
-    bool _timeConstrainedEnabled;
-    bool _timeAdvancePending;
-    SGTimeStamp _federateTime;
+    SGWeakPtr<RTI13Federate> _federate;
 };
 
 } // namespace simgear

Modified: simgear/trunk/simgear/hla/RTI13Federate.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTI13Federate.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTI13Federate.cxx (original)
+++ simgear/trunk/simgear/hla/RTI13Federate.cxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -21,92 +21,959 @@
 
 namespace simgear {
 
-RTI13Federate::RTI13Federate() :
-    _tickTimeout(10),
-    _ambassador(new RTI13Ambassador)
-{
+static std::string toStdString(const char* n)
+{
+    if (!n)
+        return std::string();
+    return std::string(n);
+}
+
+/// Just the interface class doing the callbacks into the parent class
+struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador {
+    FederateAmbassador() :
+        _timeRegulationEnabled(false),
+        _timeConstrainedEnabled(false),
+        _timeAdvancePending(false)
+    {
+    }
+    virtual ~FederateAmbassador()
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    /// Generic callback to execute some notification on objects in a way that they are not prone to
+    /// ConcurrentAccess exceptions.
+    class QueueCallback : public SGReferenced {
+    public:
+        virtual ~QueueCallback() {}
+        virtual void operator()(FederateAmbassador& self) = 0;
+    };
+    class TagQueueCallback : public QueueCallback {
+    public:
+        TagQueueCallback(const char* tag)
+        {
+            if (tag)
+                _tag.setData(tag, std::strlen(tag) + 1);
+            else
+                _tag.setData("", 1);
+        }
+        virtual ~TagQueueCallback()
+        { }
+        RTIData _tag;
+    };
+
+    /// RTI federate ambassador callback functions.
+    virtual void synchronizationPointRegistrationSucceeded(const char* label)
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    virtual void synchronizationPointRegistrationFailed(const char* label)
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    virtual void announceSynchronizationPoint(const char* label, const char* tag)
+        throw (RTI::FederateInternalError)
+    {
+        _pendingSyncLabels.insert(toStdString(label));
+    }
+
+    virtual void federationSynchronized(const char* label)
+        throw (RTI::FederateInternalError)
+    {
+        std::string s = toStdString(label);
+        _pendingSyncLabels.erase(s);
+        _syncronizedSyncLabels.insert(s);
+    }
+
+    virtual void initiateFederateSave(const char* label)
+        throw (RTI::UnableToPerformSave,
+               RTI::FederateInternalError)
+    {
+    }
+
+    virtual void federationSaved()
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    virtual void federationNotSaved()
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    virtual void requestFederationRestoreSucceeded(const char* label)
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    virtual void requestFederationRestoreFailed(const char* label, const char* reason)
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    virtual void federationRestoreBegun()
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    virtual void initiateFederateRestore(const char* label, RTI::FederateHandle federateHandle)
+        throw (RTI::SpecifiedSaveLabelDoesNotExist,
+               RTI::CouldNotRestore,
+               RTI::FederateInternalError)
+    {
+    }
+
+    virtual void federationRestored()
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    virtual void federationNotRestored()
+        throw (RTI::FederateInternalError)
+    {
+    }
+
+    // Declaration Management
+    class StartRegistrationForObjectClassCallback : public QueueCallback {
+    public:
+        StartRegistrationForObjectClassCallback(RTI::ObjectClassHandle objectClassHandle) :
+            _objectClassHandle(objectClassHandle)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.startRegistrationForObjectClassCallback(_objectClassHandle); }
+    private:
+        RTI::ObjectClassHandle _objectClassHandle;
+    };
+    virtual void startRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle)
+        throw (RTI::ObjectClassNotPublished,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new StartRegistrationForObjectClassCallback(objectClassHandle)); }
+    void startRegistrationForObjectClassCallback(RTI::ObjectClassHandle objectClassHandle)
+    {
+        ObjectClassMap::iterator i = _objectClassMap.find(objectClassHandle);
+        if (i == _objectClassMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->startRegistration();
+    }
+
+    class StopRegistrationForObjectClassCallback : public QueueCallback {
+    public:
+        StopRegistrationForObjectClassCallback(RTI::ObjectClassHandle objectClassHandle) :
+            _objectClassHandle(objectClassHandle)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.stopRegistrationForObjectClassCallback(_objectClassHandle); }
+    private:
+        RTI::ObjectClassHandle _objectClassHandle;
+    };
+    virtual void stopRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle)
+        throw (RTI::ObjectClassNotPublished,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new StopRegistrationForObjectClassCallback(objectClassHandle)); }
+    void stopRegistrationForObjectClassCallback(RTI::ObjectClassHandle objectClassHandle)
+    {
+        ObjectClassMap::iterator i = _objectClassMap.find(objectClassHandle);
+        if (i == _objectClassMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->stopRegistration();
+    }
+
+    virtual void turnInteractionsOn(RTI::InteractionClassHandle interactionClassHandle)
+        throw (RTI::InteractionClassNotPublished,
+               RTI::FederateInternalError)
+    {
+    }
+
+    virtual void turnInteractionsOff(RTI::InteractionClassHandle interactionClassHandle)
+        throw (RTI::InteractionClassNotPublished,
+               RTI::FederateInternalError)
+    {
+    }
+
+    // Object Management
+    class DiscoverObjectCallback : public TagQueueCallback {
+    public:
+        DiscoverObjectCallback(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const char *tag) :
+            TagQueueCallback(tag),
+            _objectHandle(objectHandle),
+            _objectClassHandle(objectClassHandle)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.discoverObjectInstanceCallback(_objectHandle, _objectClassHandle, _tag); }
+    private:
+        RTI::ObjectHandle _objectHandle;
+        RTI::ObjectClassHandle _objectClassHandle;
+    };
+    virtual void discoverObjectInstance(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const char* tag)
+        throw (RTI::CouldNotDiscover,
+               RTI::ObjectClassNotKnown,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new DiscoverObjectCallback(objectHandle, objectClassHandle, tag)); }
+    void discoverObjectInstanceCallback(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const RTIData& tag)
+    {
+        ObjectClassMap::iterator i = _objectClassMap.find(objectClassHandle);
+        if (i == _objectClassMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        SGSharedPtr<RTI13ObjectInstance> objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, _rtiAmbassador.get(), false);
+        _objectInstanceMap[objectHandle] = objectInstance;
+        i->second->discoverInstance(objectInstance.get(), tag);
+    }
+
+    class ReflectAttributeValuesTimestampCallback : public TagQueueCallback {
+    public:
+        ReflectAttributeValuesTimestampCallback(RTI::ObjectHandle objectHandle,
+                                                RTI13AttributeHandleDataPairList& attributeHandleDataPairList,
+                                                const SGTimeStamp& timeStamp, const char *tag) :
+            TagQueueCallback(tag),
+            _objectHandle(objectHandle),
+            _timeStamp(timeStamp)
+        {
+            _attributeHandleDataPairList.swap(attributeHandleDataPairList);
+        }
+        virtual void operator()(FederateAmbassador& self)
+        {
+            self.reflectAttributeValuesCallback(_objectHandle, _attributeHandleDataPairList, _timeStamp, _tag);
+            self.freeAttributeHandleDataPairList(_attributeHandleDataPairList);
+        }
+    private:
+        RTI::ObjectHandle _objectHandle;
+        RTI13AttributeHandleDataPairList _attributeHandleDataPairList;
+        SGTimeStamp _timeStamp;
+    };
+    virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet,
+                                        const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::FederateOwnsAttributes,
+               RTI::InvalidFederationTime,
+               RTI::FederateInternalError)
+    {
+        RTI13AttributeHandleDataPairList attributeHandleDataPairList;
+
+        RTI::ULong numAttribs = attributeValuePairSet.size();
+        for (RTI::ULong i = 0; i < numAttribs; ++i) {
+            appendAttributeHandleDataPair(attributeHandleDataPairList);
+            attributeHandleDataPairList.back().first = attributeValuePairSet.getHandle(i);
+            RTI::ULong length = attributeValuePairSet.getValueLength(i);
+            attributeHandleDataPairList.back().second.resize(length);
+            attributeValuePairSet.getValue(i, attributeHandleDataPairList.back().second.data(), length);
+        }
+
+        _queueCallbackList.push_back(new ReflectAttributeValuesTimestampCallback(objectHandle, attributeHandleDataPairList,
+                                                                                 RTI13Ambassador::toTimeStamp(fedTime), tag));
+    }
+    void reflectAttributeValuesCallback(RTI::ObjectHandle objectHandle, RTI13AttributeHandleDataPairList& attributeHandleDataPairList,
+                                        const SGTimeStamp& timeStamp, const RTIData& tag)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->reflectAttributeValues(attributeHandleDataPairList, timeStamp, tag);
+    }
+
+    class ReflectAttributeValuesCallback : public TagQueueCallback {
+    public:
+        ReflectAttributeValuesCallback(RTI::ObjectHandle objectHandle, RTI13AttributeHandleDataPairList& attributeHandleDataPairList,
+                                       const char *tag) :
+            TagQueueCallback(tag),
+            _objectHandle(objectHandle)
+        {
+            _attributeHandleDataPairList.swap(attributeHandleDataPairList);
+        }
+        virtual void operator()(FederateAmbassador& self)
+        {
+            self.reflectAttributeValuesCallback(_objectHandle, _attributeHandleDataPairList, _tag);
+            self.freeAttributeHandleDataPairList(_attributeHandleDataPairList);
+        }
+    private:
+        RTI::ObjectHandle _objectHandle;
+        RTI13AttributeHandleDataPairList _attributeHandleDataPairList;
+    };
+    virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet,
+                                        const char* tag)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::FederateOwnsAttributes,
+               RTI::FederateInternalError)
+    {
+        RTI13AttributeHandleDataPairList attributeHandleDataPairList;
+
+        RTI::ULong numAttribs = attributeValuePairSet.size();
+        for (RTI::ULong i = 0; i < numAttribs; ++i) {
+            appendAttributeHandleDataPair(attributeHandleDataPairList);
+            attributeHandleDataPairList.back().first = attributeValuePairSet.getHandle(i);
+            RTI::ULong length = attributeValuePairSet.getValueLength(i);
+            attributeHandleDataPairList.back().second.resize(length);
+            attributeValuePairSet.getValue(i, attributeHandleDataPairList.back().second.data(), length);
+        }
+
+        _queueCallbackList.push_back(new ReflectAttributeValuesCallback(objectHandle, attributeHandleDataPairList, tag));
+    }
+    void reflectAttributeValuesCallback(RTI::ObjectHandle objectHandle, RTI13AttributeHandleDataPairList& attributeHandleDataPairList,
+                                        const RTIData& tag)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->reflectAttributeValues(attributeHandleDataPairList, tag);
+    }
+
+    virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters,
+                                    const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
+        throw (RTI::InteractionClassNotKnown,
+               RTI::InteractionParameterNotKnown,
+               RTI::InvalidFederationTime,
+               RTI::FederateInternalError)
+    {
+    }
+
+    virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle,
+                                    const RTI::ParameterHandleValuePairSet& parameters, const char* tag)
+        throw (RTI::InteractionClassNotKnown,
+               RTI::InteractionParameterNotKnown,
+               RTI::FederateInternalError)
+    {
+    }
+
+    class RemoveObjectTimestampCallback : public TagQueueCallback {
+    public:
+        RemoveObjectTimestampCallback(RTI::ObjectHandle objectHandle, const SGTimeStamp& timeStamp, const char* tag) :
+            TagQueueCallback(tag),
+            _objectHandle(objectHandle),
+            _timeStamp(timeStamp)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.removeObjectInstanceCallback(_objectHandle, _timeStamp, _tag); }
+    private:
+        RTI::ObjectHandle _objectHandle;
+        SGTimeStamp _timeStamp;
+    };
+    virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const RTI::FedTime& fedTime,
+                                      const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
+        throw (RTI::ObjectNotKnown,
+               RTI::InvalidFederationTime,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new RemoveObjectTimestampCallback(objectHandle, RTI13Ambassador::toTimeStamp(fedTime), tag)); }
+    void removeObjectInstanceCallback(RTI::ObjectHandle objectHandle, const SGTimeStamp& timeStamp, const RTIData& tag)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (i->second.valid())
+            i->second->removeInstance(tag);
+        _objectInstanceMap.erase(i);
+    }
+
+    class RemoveObjectCallback : public TagQueueCallback {
+    public:
+        RemoveObjectCallback(RTI::ObjectHandle objectHandle, const char* tag) :
+            TagQueueCallback(tag),
+            _objectHandle(objectHandle)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.removeObjectInstanceCallback(_objectHandle, _tag); }
+    private:
+        RTI::ObjectHandle _objectHandle;
+    };
+    virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const char* tag)
+        throw (RTI::ObjectNotKnown,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new RemoveObjectCallback(objectHandle, tag)); }
+    void removeObjectInstanceCallback(RTI::ObjectHandle objectHandle, const RTIData& tag)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (i->second.valid())
+            i->second->removeInstance(tag);
+        _objectInstanceMap.erase(i);
+    }
+
+    class AttributeHandleSetCallback : public QueueCallback {
+    public:
+        AttributeHandleSetCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributeHandleSet) :
+            _objectHandle(objectHandle)
+        {
+            RTI::ULong numAttribs = attributeHandleSet.size();
+            _attributes.reserve(numAttribs);
+            for (RTI::ULong i = 0; i < numAttribs; ++i)
+                _attributes.push_back(attributeHandleSet.getHandle(i));
+        }
+    protected:
+        RTI::ObjectHandle _objectHandle;
+        std::vector<RTI::AttributeHandle> _attributes;
+    };
+    class AttributesInScopeCallback : public AttributeHandleSetCallback {
+    public:
+        AttributesInScopeCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) :
+            AttributeHandleSetCallback(objectHandle, attributes)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.attributesInScopeCallback(_objectHandle, _attributes); }
+    };
+    virtual void attributesInScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new AttributesInScopeCallback(objectHandle, attributes)); }
+    void attributesInScopeCallback(RTI::ObjectHandle objectHandle, const std::vector<RTI::AttributeHandle>& attributes)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->attributesInScope(attributes);
+    }
+
+    class AttributesOutOfScopeCallback : public AttributeHandleSetCallback {
+    public:
+        AttributesOutOfScopeCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) :
+            AttributeHandleSetCallback(objectHandle, attributes)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.attributesOutOfScopeCallback(_objectHandle, _attributes); }
+    };
+    virtual void attributesOutOfScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new AttributesOutOfScopeCallback(objectHandle, attributes)); }
+    void attributesOutOfScopeCallback(RTI::ObjectHandle objectHandle, const std::vector<RTI::AttributeHandle>& attributes)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->attributesOutOfScope(attributes);
+    }
+
+    class ProvideAttributeValueUpdateCallback : public AttributeHandleSetCallback {
+    public:
+        ProvideAttributeValueUpdateCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) :
+            AttributeHandleSetCallback(objectHandle, attributes)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.provideAttributeValueUpdateCallback(_objectHandle, _attributes); }
+    };
+    virtual void provideAttributeValueUpdate(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::AttributeNotOwned,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new ProvideAttributeValueUpdateCallback(objectHandle, attributes)); }
+    void provideAttributeValueUpdateCallback(RTI::ObjectHandle objectHandle, const std::vector<RTI::AttributeHandle>& attributes)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->provideAttributeValueUpdate(attributes);
+    }
+
+    class TurnUpdatesOnForObjectInstanceCallback : public AttributeHandleSetCallback {
+    public:
+        TurnUpdatesOnForObjectInstanceCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) :
+            AttributeHandleSetCallback(objectHandle, attributes)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.turnUpdatesOnForObjectInstanceCallback(_objectHandle, _attributes); }
+    };
+    virtual void turnUpdatesOnForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotOwned,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new TurnUpdatesOnForObjectInstanceCallback(objectHandle, attributes)); }
+    void turnUpdatesOnForObjectInstanceCallback(RTI::ObjectHandle objectHandle, const std::vector<RTI::AttributeHandle>& attributes)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->turnUpdatesOnForObjectInstance(attributes);
+    }
+
+    class TurnUpdatesOffForObjectInstanceCallback : public AttributeHandleSetCallback {
+    public:
+        TurnUpdatesOffForObjectInstanceCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) :
+            AttributeHandleSetCallback(objectHandle, attributes)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.turnUpdatesOffForObjectInstanceCallback(_objectHandle, _attributes); }
+    };
+    virtual void turnUpdatesOffForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotOwned,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new TurnUpdatesOffForObjectInstanceCallback(objectHandle, attributes)); }
+    void turnUpdatesOffForObjectInstanceCallback(RTI::ObjectHandle objectHandle, const std::vector<RTI::AttributeHandle>& attributes)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->turnUpdatesOffForObjectInstance(attributes);
+    }
+
+    // Ownership Management
+    class RequestAttributeOwnershipAssumptionCallback : public AttributeHandleSetCallback {
+    public:
+        RequestAttributeOwnershipAssumptionCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes, const RTIData& tag) :
+            AttributeHandleSetCallback(objectHandle, attributes),
+            _tag(tag)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.requestAttributeOwnershipAssumptionCallback(_objectHandle, _attributes, _tag); }
+    protected:
+        RTIData _tag;
+    };
+    virtual void requestAttributeOwnershipAssumption(RTI::ObjectHandle objectHandle,
+                                                     const RTI::AttributeHandleSet& attributes, const char* tag)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::AttributeAlreadyOwned,
+               RTI::AttributeNotPublished,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new RequestAttributeOwnershipAssumptionCallback(objectHandle, attributes, tagToData(tag))); }
+    void requestAttributeOwnershipAssumptionCallback(RTI::ObjectHandle objectHandle, std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->requestAttributeOwnershipAssumption(attributes, tag);
+    }
+
+    class AttributeOwnershipDivestitureNotificationCallback : public AttributeHandleSetCallback {
+    public:
+        AttributeOwnershipDivestitureNotificationCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) :
+            AttributeHandleSetCallback(objectHandle, attributes)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.attributeOwnershipDivestitureNotificationCallback(_objectHandle, _attributes); }
+    };
+    virtual void attributeOwnershipDivestitureNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::AttributeNotOwned,
+               RTI::AttributeDivestitureWasNotRequested,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new AttributeOwnershipDivestitureNotificationCallback(objectHandle, attributes)); }
+    void attributeOwnershipDivestitureNotificationCallback(RTI::ObjectHandle objectHandle, const std::vector<RTI::AttributeHandle>& attributes)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->attributeOwnershipDivestitureNotification(attributes);
+    }
+
+    class AttributeOwnershipAcquisitionNotificationCallback : public AttributeHandleSetCallback {
+    public:
+        AttributeOwnershipAcquisitionNotificationCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) :
+            AttributeHandleSetCallback(objectHandle, attributes)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.attributeOwnershipAcquisitionNotificationCallback(_objectHandle, _attributes); }
+    };
+    virtual void attributeOwnershipAcquisitionNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::AttributeAcquisitionWasNotRequested,
+               RTI::AttributeAlreadyOwned,
+               RTI::AttributeNotPublished,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new AttributeOwnershipAcquisitionNotificationCallback(objectHandle, attributes)); }
+    void attributeOwnershipAcquisitionNotificationCallback(RTI::ObjectHandle objectHandle, const std::vector<RTI::AttributeHandle>& attributes)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->attributeOwnershipAcquisitionNotification(attributes);
+    }
+
+    class AttributeOwnershipUnavailableCallback : public AttributeHandleSetCallback {
+    public:
+        AttributeOwnershipUnavailableCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) :
+            AttributeHandleSetCallback(objectHandle, attributes)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.attributeOwnershipUnavailableCallback(_objectHandle, _attributes); }
+    };
+    virtual void attributeOwnershipUnavailable(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::AttributeAlreadyOwned,
+               RTI::AttributeAcquisitionWasNotRequested,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new AttributeOwnershipUnavailableCallback(objectHandle, attributes)); }
+    void attributeOwnershipUnavailableCallback(RTI::ObjectHandle objectHandle, const std::vector<RTI::AttributeHandle>& attributes)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->attributeOwnershipUnavailable(attributes);
+    }
+
+    class RequestAttributeOwnershipReleaseCallback : public AttributeHandleSetCallback {
+    public:
+        RequestAttributeOwnershipReleaseCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes, const RTIData& tag) :
+            AttributeHandleSetCallback(objectHandle, attributes),
+            _tag(tag)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.requestAttributeOwnershipReleaseCallback(_objectHandle, _attributes, _tag); }
+    protected:
+        RTIData _tag;
+    };
+    virtual void requestAttributeOwnershipRelease(RTI::ObjectHandle objectHandle,
+                                                  const RTI::AttributeHandleSet& attributes, const char* tag)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::AttributeNotOwned,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new RequestAttributeOwnershipReleaseCallback(objectHandle, attributes, tagToData(tag))); }
+    void requestAttributeOwnershipReleaseCallback(RTI::ObjectHandle objectHandle, std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->requestAttributeOwnershipRelease(attributes, tag);
+    }
+
+    class ConfirmAttributeOwnershipAcquisitionCancellationCallback : public AttributeHandleSetCallback {
+    public:
+        ConfirmAttributeOwnershipAcquisitionCancellationCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) :
+            AttributeHandleSetCallback(objectHandle, attributes)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.confirmAttributeOwnershipAcquisitionCancellationCallback(_objectHandle, _attributes); }
+    };
+    virtual void confirmAttributeOwnershipAcquisitionCancellation(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::AttributeAlreadyOwned,
+               RTI::AttributeAcquisitionWasNotCanceled,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new ConfirmAttributeOwnershipAcquisitionCancellationCallback(objectHandle, attributes)); }
+    void confirmAttributeOwnershipAcquisitionCancellationCallback(RTI::ObjectHandle objectHandle, const std::vector<RTI::AttributeHandle>& attributes)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->confirmAttributeOwnershipAcquisitionCancellation(attributes);
+    }
+
+    class InformAttributeOwnershipCallback : public QueueCallback {
+    public:
+        InformAttributeOwnershipCallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle) :
+            _objectHandle(objectHandle),
+            _attributeHandle(attributeHandle),
+            _federateHandle(federateHandle)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.informAttributeOwnershipCallback(_objectHandle, _attributeHandle, _federateHandle); }
+    private:
+        RTI::ObjectHandle _objectHandle;
+        RTI::AttributeHandle _attributeHandle;
+        RTI::FederateHandle _federateHandle;
+    };
+    virtual void informAttributeOwnership(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle,
+                                          RTI::FederateHandle federateHandle)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new InformAttributeOwnershipCallback(objectHandle, attributeHandle, federateHandle)); }
+    void informAttributeOwnershipCallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->informAttributeOwnership(attributeHandle, federateHandle);
+    }
+
+    class AttributeIsNotOwnedCallback : public QueueCallback {
+    public:
+        AttributeIsNotOwnedCallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) :
+            _objectHandle(objectHandle),
+            _attributeHandle(attributeHandle)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.attributeIsNotOwnedCallback(_objectHandle, _attributeHandle); }
+    private:
+        RTI::ObjectHandle _objectHandle;
+        RTI::AttributeHandle _attributeHandle;
+    };
+    virtual void attributeIsNotOwned(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new AttributeIsNotOwnedCallback(objectHandle, attributeHandle)); }
+    void attributeIsNotOwnedCallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->attributeIsNotOwned(attributeHandle);
+    }
+
+    class AttributeOwnedByRTICallback : public QueueCallback {
+    public:
+        AttributeOwnedByRTICallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) :
+            _objectHandle(objectHandle),
+            _attributeHandle(attributeHandle)
+        { }
+        virtual void operator()(FederateAmbassador& self)
+        { self.attributeOwnedByRTICallback(_objectHandle, _attributeHandle); }
+    private:
+        RTI::ObjectHandle _objectHandle;
+        RTI::AttributeHandle _attributeHandle;
+    };
+    virtual void attributeOwnedByRTI(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
+        throw (RTI::ObjectNotKnown,
+               RTI::AttributeNotKnown,
+               RTI::FederateInternalError)
+    { _queueCallbackList.push_back(new AttributeOwnedByRTICallback(objectHandle, attributeHandle)); }
+    void attributeOwnedByRTICallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
+    {
+        ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+        if (i == _objectInstanceMap.end())
+            return;
+        if (!i->second.valid())
+            return;
+        i->second->attributeOwnedByRTI(attributeHandle);
+    }
+
+    // Time Management
+    virtual void timeRegulationEnabled(const RTI::FedTime& fedTime)
+        throw (RTI::InvalidFederationTime,
+               RTI::EnableTimeRegulationWasNotPending,
+               RTI::FederateInternalError)
+    {
+        _timeRegulationEnabled = true;
+        SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeRegulationEnabled: " << RTI13Ambassador::toTimeStamp(fedTime));
+    }
+
+    virtual void timeConstrainedEnabled(const RTI::FedTime& fedTime)
+        throw (RTI::InvalidFederationTime,
+               RTI::EnableTimeConstrainedWasNotPending,
+               RTI::FederateInternalError)
+    {
+        _timeConstrainedEnabled = true;
+        SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeConstrainedEnabled: " << RTI13Ambassador::toTimeStamp(fedTime));
+    }
+
+    virtual void timeAdvanceGrant(const RTI::FedTime& fedTime)
+        throw (RTI::InvalidFederationTime,
+               RTI::TimeAdvanceWasNotInProgress,
+               RTI::FederateInternalError)
+    {
+        _timeAdvancePending = false;
+        // SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeAdvanceGrant: " << RTI13Ambassador::toTimeStamp(fedTime));
+    }
+
+    virtual void requestRetraction(RTI::EventRetractionHandle eventRetractionHandle)
+        throw (RTI::EventNotKnown,
+               RTI::FederateInternalError)
+    {
+        // No retraction concept yet
+    }
+
+    // processes the queues that filled up during the past
+    void processQueues()
+    {
+        while (!_queueCallbackList.empty()) {
+            (*_queueCallbackList.front())(*this);
+            // _queueCallbackListPool.splice();
+            _queueCallbackList.pop_front();
+        }
+    }
+
+    bool getFederationSynchronizationPointAnnounced(const std::string& label)
+    { return _pendingSyncLabels.find(label) != _pendingSyncLabels.end(); }
+    bool getFederationSynchronized(const std::string& label)
+    {
+        std::set<std::string>::iterator i = _syncronizedSyncLabels.find(label);
+        if (i == _syncronizedSyncLabels.end())
+            return false;
+        _syncronizedSyncLabels.erase(i);
+        return true;
+    }
+
+    // The rtiambassador to issue requests
+    SGSharedPtr<RTI13Ambassador> _rtiAmbassador;
+
+    // All the sync labels we got an announcement for
+    std::set<std::string> _pendingSyncLabels;
+    std::set<std::string> _syncronizedSyncLabels;
+
+    // All that calls back into user code is just queued.
+    // That is to make sure we do not call recursively into the RTI
+    typedef std::list<SGSharedPtr<QueueCallback> > QueueCallbackList;
+    QueueCallbackList _queueCallbackList;
+    // QueueCallbackList _queueCallbackListPool;
+
+    RTI13AttributeHandleDataPairList _attributeHandleDataPairPool;
+    void appendAttributeHandleDataPair(RTI13AttributeHandleDataPairList& attributeHandleDataPairList)
+    {
+        if (_attributeHandleDataPairPool.empty())
+            attributeHandleDataPairList.push_back(RTI13AttributeHandleDataPair());
+        else
+            attributeHandleDataPairList.splice(attributeHandleDataPairList.end(),
+                                               _attributeHandleDataPairPool, _attributeHandleDataPairPool.begin());
+    }
+    void freeAttributeHandleDataPairList(RTI13AttributeHandleDataPairList& attributeHandleDataPairList)
+    { _attributeHandleDataPairPool.splice(_attributeHandleDataPairPool.end(), attributeHandleDataPairList); }
+
+    // Top level information for dispatching federate object attribute updates
+    typedef std::map<RTI::ObjectHandle, SGSharedPtr<RTI13ObjectInstance> > ObjectInstanceMap;
+    // Map of all available objects
+    ObjectInstanceMap _objectInstanceMap;
+
+    // Top level information for dispatching creation of federate objects
+    typedef std::map<RTI::ObjectClassHandle, SGSharedPtr<RTI13ObjectClass> > ObjectClassMap;
+    ObjectClassMap _objectClassMap;
+
+    bool _timeRegulationEnabled;
+    bool _timeConstrainedEnabled;
+    bool _timeAdvancePending;
+
+private:
+    const RTIData& tagToData(const char* tag)
+    {
+        if (tag)
+            _cachedTag.setData(tag, std::strlen(tag) + 1);
+        else
+            _cachedTag.setData("", 1);
+        return _cachedTag;
+    }
+    RTIData _cachedTag;
+};
+
+RTI13Federate::RTI13Federate(const std::list<std::string>& stringList) :
+    _joined(false),
+    _ambassador(new RTI13Ambassador),
+    _federateAmbassador(new FederateAmbassador)
+{
+    _ambassador->_federate = this;
+    _federateAmbassador->_rtiAmbassador = _ambassador;
+    if (stringList.empty()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Ignoring non empty connect arguments while connecting to an RTI13 federation!");
+    }
 }
 
 RTI13Federate::~RTI13Federate()
 {
-}
-
-bool
+    if (_joined)
+        _ambassador->resignFederationExecution();
+    delete _federateAmbassador;
+}
+
+RTI13Federate::FederationManagementResult
 RTI13Federate::createFederationExecution(const std::string& federationName, const std::string& objectModel)
 {
     try {
         _ambassador->createFederationExecution(federationName, objectModel);
-        return true;
+        return FederationManagementSuccess;
     } catch (RTI::FederationExecutionAlreadyExists& e) {
-        return true;
+        return FederationManagementFail;
     } catch (RTI::CouldNotOpenFED& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::ErrorReadingFED& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::ConcurrentAccessAttempted& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::RTIinternalError& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason);
-        return false;
-    }
-}
-
-bool
+        return FederationManagementFatal;
+    }
+}
+
+RTI13Federate::FederationManagementResult
 RTI13Federate::destroyFederationExecution(const std::string& federation)
 {
     try {
         _ambassador->destroyFederationExecution(federation);
-        return true;
+        return FederationManagementSuccess;
     } catch (RTI::FederatesCurrentlyJoined& e) {
-        return true;
+        return FederationManagementFail;
     } catch (RTI::FederationExecutionDoesNotExist& e) {
-        return true;
+        return FederationManagementFail;
     } catch (RTI::ConcurrentAccessAttempted& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not destroy federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::RTIinternalError& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not destroy federation execution: " << e._name << " " << e._reason);
-        return false;
-    }
-}
-
-bool
+        return FederationManagementFatal;
+    }
+}
+
+RTI13Federate::FederationManagementResult
 RTI13Federate::join(const std::string& federateType, const std::string& federationName)
 {
     try {
-        _federateHandle = _ambassador->joinFederationExecution(federateType, federationName);
+        _federateHandle = _ambassador->joinFederationExecution(federateType, federationName, _federateAmbassador);
         SG_LOG(SG_NETWORK, SG_INFO, "RTI: Joined federation \""
                << federationName << "\" as \"" << federateType << "\"");
-        setFederateType(federateType);
-        setFederationName(federationName);
-        return true;
+        _joined = true;
+        return FederationManagementSuccess;
     } catch (RTI::FederateAlreadyExecutionMember& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::FederationExecutionDoesNotExist& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFail;
     } catch (RTI::CouldNotOpenFED& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::ErrorReadingFED& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::ConcurrentAccessAttempted& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::SaveInProgress& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::RestoreInProgress& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     } catch (RTI::RTIinternalError& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason);
-        return false;
+        return FederationManagementFatal;
     }
 }
 
@@ -116,6 +983,7 @@
     try {
         _ambassador->resignFederationExecution();
         SG_LOG(SG_NETWORK, SG_INFO, "RTI: Resigned from federation.");
+        _joined = false;
         _federateHandle = -1;
         return true;
     } catch (RTI::FederateOwnsAttributes& e) {
@@ -134,6 +1002,12 @@
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
         return false;
     }
+}
+
+bool
+RTI13Federate::getJoined() const
+{
+    return _joined;
 }
 
 bool
@@ -162,13 +1036,9 @@
 }
 
 bool
-RTI13Federate::waitForFederationSynchronizationPointAnnounced(const std::string& label)
-{
-    while (!_ambassador->getFederationSynchronizationPointAnnounced(label)) {
-        _ambassador->tick(_tickTimeout, 0);
-        _ambassador->processQueues();
-    }
-    return true;
+RTI13Federate::getFederationSynchronizationPointAnnounced(const std::string& label)
+{
+    return _federateAmbassador->getFederationSynchronizationPointAnnounced(label);
 }
 
 bool
@@ -200,13 +1070,9 @@
 }
 
 bool
-RTI13Federate::waitForFederationSynchronized(const std::string& label)
-{
-    while (!_ambassador->getFederationSynchronized(label)) {
-        _ambassador->tick(_tickTimeout, 0);
-        _ambassador->processQueues();
-    }
-    return true;
+RTI13Federate::getFederationSynchronized(const std::string& label)
+{
+    return _federateAmbassador->getFederationSynchronized(label);
 }
 
 bool
@@ -217,7 +1083,7 @@
         return false;
     }
 
-    if (_ambassador->getTimeConstrainedEnabled()) {
+    if (_federateAmbassador->_timeConstrainedEnabled) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time constrained is already enabled.");
         return false;
     }
@@ -225,34 +1091,29 @@
     try {
         _ambassador->enableTimeConstrained();
     } catch (RTI::TimeConstrainedAlreadyEnabled& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::EnableTimeConstrainedPending& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::TimeAdvanceAlreadyInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::ConcurrentAccessAttempted& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::FederateNotExecutionMember& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::SaveInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::RestoreInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::RTIinternalError& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    }
-
-    while (!_ambassador->getTimeConstrainedEnabled()) {
-        _ambassador->tick(_tickTimeout, 0);
-        _ambassador->processQueues();
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained: " << e._name << " " << e._reason);
+        return false;
     }
 
     return true;
@@ -266,34 +1127,41 @@
         return false;
     }
 
-    if (!_ambassador->getTimeConstrainedEnabled()) {
+    if (!_federateAmbassador->_timeConstrainedEnabled) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time constrained is not enabled.");
         return false;
     }
 
     try {
         _ambassador->disableTimeConstrained();
+        _federateAmbassador->_timeConstrainedEnabled = false;
     } catch (RTI::TimeConstrainedWasNotEnabled& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time constrained: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::FederateNotExecutionMember& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::ConcurrentAccessAttempted& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time constrained: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time constrained: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::SaveInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time constrained: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::RestoreInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::RTIinternalError& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time constrained: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time constrained: " << e._name << " " << e._reason);
         return false;
     }
 
     return true;
+}
+
+bool
+RTI13Federate::getTimeConstrainedEnabled()
+{
+    return _federateAmbassador->_timeConstrainedEnabled;
 }
 
 bool
@@ -304,48 +1172,43 @@
         return false;
     }
 
-    if (_ambassador->getTimeRegulationEnabled()) {
+    if (_federateAmbassador->_timeRegulationEnabled) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time regulation already enabled.");
         return false;
     }
 
     try {
-        _ambassador->enableTimeRegulation(SGTimeStamp(), lookahead);
+        _ambassador->enableTimeRegulation(lookahead);
     } catch (RTI::TimeRegulationAlreadyEnabled& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::EnableTimeRegulationPending& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::TimeAdvanceAlreadyInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::InvalidFederationTime& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::InvalidLookahead& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::ConcurrentAccessAttempted& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::FederateNotExecutionMember& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::SaveInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::RestoreInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::RTIinternalError& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    }
-
-    while (!_ambassador->getTimeRegulationEnabled()) {
-        _ambassador->tick(_tickTimeout, 0);
-        _ambassador->processQueues();
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation: " << e._name << " " << e._reason);
+        return false;
     }
 
     return true;
@@ -359,30 +1222,31 @@
         return false;
     }
 
-    if (!_ambassador->getTimeRegulationEnabled()) {
+    if (!_federateAmbassador->_timeRegulationEnabled) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time regulation is not enabled.");
         return false;
     }
 
     try {
         _ambassador->disableTimeRegulation();
+        _federateAmbassador->_timeRegulationEnabled = false;
     } catch (RTI::TimeRegulationWasNotEnabled& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::ConcurrentAccessAttempted& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::FederateNotExecutionMember& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::SaveInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::RestoreInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::RTIinternalError& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation: " << e._name << " " << e._reason);
         return false;
     }
 
@@ -390,80 +1254,322 @@
 }
 
 bool
-RTI13Federate::timeAdvanceRequestBy(const SGTimeStamp& dt)
+RTI13Federate::modifyLookahead(const SGTimeStamp& timeStamp)
 {
     if (!_ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate.");
-        return false;
-    }
-
-    SGTimeStamp fedTime = _ambassador->getCurrentLogicalTime() + dt;
-    return timeAdvanceRequest(fedTime);
-}
-
-bool
-RTI13Federate::timeAdvanceRequest(const SGTimeStamp& fedTime)
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead.");
+        return false;
+    }
+    try {
+        _ambassador->modifyLookahead(timeStamp);
+    } catch (RTI::InvalidLookahead& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
+        return false;
+    }
+    return true;
+}
+
+bool
+RTI13Federate::getTimeRegulationEnabled()
+{
+    return _federateAmbassador->_timeRegulationEnabled;
+}
+
+bool
+RTI13Federate::timeAdvanceRequest(const SGTimeStamp& timeStamp)
 {
     if (!_ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate.");
-        return false;
-    }
-
-    try {
-        _ambassador->timeAdvanceRequest(fedTime);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time at unconnected federate.");
+        return false;
+    }
+
+    try {
+        _ambassador->timeAdvanceRequest(timeStamp);
+        _federateAmbassador->_timeAdvancePending = true;
     } catch (RTI::InvalidFederationTime& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::FederationTimeAlreadyPassed& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::TimeAdvanceAlreadyInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::EnableTimeRegulationPending& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::EnableTimeConstrainedPending& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::FederateNotExecutionMember& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::ConcurrentAccessAttempted& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::SaveInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
         return false;
     } catch (RTI::RestoreInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    } catch (RTI::RTIinternalError& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason);
-        return false;
-    }
-
-    while (_ambassador->getTimeAdvancePending()) {
-        _ambassador->tick(_tickTimeout, 0);
-        _ambassador->processQueues();
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
     }
 
     return true;
 }
 
 bool
-RTI13Federate::tick()
+RTI13Federate::timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp)
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time at unconnected federate.");
+        return false;
+    }
+
+    try {
+        _ambassador->timeAdvanceRequestAvailable(timeStamp);
+        _federateAmbassador->_timeAdvancePending = true;
+    } catch (RTI::InvalidFederationTime& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederationTimeAlreadyPassed& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::TimeAdvanceAlreadyInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::EnableTimeRegulationPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::EnableTimeConstrainedPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason);
+        return false;
+    }
+
+    return true;
+}
+
+bool
+RTI13Federate::flushQueueRequest(const SGTimeStamp& timeStamp)
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue at unconnected federate.");
+        return false;
+    }
+
+    try {
+        _ambassador->flushQueueRequest(timeStamp);
+        _federateAmbassador->_timeAdvancePending = true;
+    } catch (RTI::InvalidFederationTime& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederationTimeAlreadyPassed& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::TimeAdvanceAlreadyInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::EnableTimeRegulationPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::EnableTimeConstrainedPending& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not flush queue: " << e._name << " " << e._reason);
+        return false;
+    }
+
+    return true;
+}
+
+bool
+RTI13Federate::getTimeAdvancePending()
+{
+    return _federateAmbassador->_timeAdvancePending;
+}
+
+bool
+RTI13Federate::queryFederateTime(SGTimeStamp& timeStamp)
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query federate time.");
+        return false;
+    }
+
+    try {
+        _ambassador->queryFederateTime(timeStamp);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query federate time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query federate time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query federate time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query federate time: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query federate time: " << e._name << " " << e._reason);
+        return false;
+    }
+    return true;
+}
+
+bool
+RTI13Federate::queryLookahead(SGTimeStamp& timeStamp)
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query lookahead.");
+        return false;
+    }
+
+    try {
+        _ambassador->queryLookahead(timeStamp);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query lookahead: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query lookahead: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query lookahead: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query lookahead: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query lookahead: " << e._name << " " << e._reason);
+        return false;
+    }
+    return true;
+}
+
+bool
+RTI13Federate::queryGALT(SGTimeStamp& timeStamp)
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query GALT.");
+        return false;
+    }
+
+    try {
+        return _ambassador->queryGALT(timeStamp);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query GALT: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query GALT: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query GALT: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query GALT: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query GALT: " << e._name << " " << e._reason);
+        return false;
+    }
+    return true;
+}
+
+bool
+RTI13Federate::queryLITS(SGTimeStamp& timeStamp)
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query LITS.");
+        return false;
+    }
+
+    try {
+        return _ambassador->queryLITS(timeStamp);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query LITS: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query LITS: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query LITS: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query LITS: " << e._name << " " << e._reason);
+        return false;
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query LITS: " << e._name << " " << e._reason);
+        return false;
+    }
+    return true;
+}
+
+bool
+RTI13Federate::processMessage()
 {
     bool result = _ambassador->tick();
-    _ambassador->processQueues();
+    _federateAmbassador->processQueues();
     return result;
 }
 
 bool
-RTI13Federate::tick(const double& minimum, const double& maximum)
-{
-    bool result = _ambassador->tick(minimum, maximum);
-    _ambassador->processQueues();
+RTI13Federate::processMessages(const double& minimum, const double& maximum)
+{
+    bool result = _ambassador->tick(minimum, 0);
+    _federateAmbassador->processQueues();
+    if (!result)
+        return false;
+    SGTimeStamp timeStamp = SGTimeStamp::now() + SGTimeStamp::fromSec(maximum);
+    do {
+        result = _ambassador->tick(0, 0);
+        _federateAmbassador->processQueues();
+    } while (result && SGTimeStamp::now() <= timeStamp);
     return result;
 }
 
@@ -471,7 +1577,16 @@
 RTI13Federate::createObjectClass(const std::string& objectClassName, HLAObjectClass* hlaObjectClass)
 {
     try {
-        return _ambassador->createObjectClass(objectClassName, hlaObjectClass);
+        RTI::ObjectClassHandle objectClassHandle;
+        objectClassHandle = _ambassador->getObjectClassHandle(objectClassName);
+        if (_federateAmbassador->_objectClassMap.find(objectClassHandle) != _federateAmbassador->_objectClassMap.end()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create object class, object class already exists!");
+            return 0;
+        }
+        RTI13ObjectClass* rtiObjectClass;
+        rtiObjectClass = new RTI13ObjectClass(hlaObjectClass, objectClassHandle, _ambassador.get());
+        _federateAmbassador->_objectClassMap[objectClassHandle] = rtiObjectClass;
+        return rtiObjectClass;
     } catch (RTI::NameNotFound& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
         return 0;
@@ -491,20 +1606,33 @@
 RTI13Federate::getObjectInstance(const std::string& objectInstanceName)
 {
     try {
-        return _ambassador->getObjectInstance(objectInstanceName);
+        RTI::ObjectHandle objectHandle;
+        objectHandle = _ambassador->getObjectInstanceHandle(objectInstanceName);
+        FederateAmbassador::ObjectInstanceMap::iterator i = _federateAmbassador->_objectInstanceMap.find(objectHandle);
+        if (i == _federateAmbassador->_objectInstanceMap.end()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object instance: ObjectInstance not found.");
+            return 0;
+        }
+        return i->second;
     } catch (RTI::ObjectNotKnown& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object instance: " << e._name << " " << e._reason);
         return 0;
     } catch (RTI::FederateNotExecutionMember& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object instance: " << e._name << " " << e._reason);
         return 0;
     } catch (RTI::ConcurrentAccessAttempted& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object instance: " << e._name << " " << e._reason);
         return 0;
     } catch (RTI::RTIinternalError& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object instance: " << e._name << " " << e._reason);
         return 0;
     }
 }
 
-}
+void
+RTI13Federate::insertObjectInstance(RTI13ObjectInstance* objectInstance)
+{
+    _federateAmbassador->_objectInstanceMap[objectInstance->getHandle()] = objectInstance;
+}
+
+}

Modified: simgear/trunk/simgear/hla/RTI13Federate.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTI13Federate.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTI13Federate.hxx (original)
+++ simgear/trunk/simgear/hla/RTI13Federate.hxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -34,39 +34,53 @@
 
 class RTI13Federate : public RTIFederate {
 public:
-    RTI13Federate();
+    RTI13Federate(const std::list<std::string>& stringList);
     virtual ~RTI13Federate();
 
-    virtual bool createFederationExecution(const std::string& federation, const std::string& objectModel);
-    virtual bool destroyFederationExecution(const std::string& federation);
+    /// Create a federation execution
+    /// Semantically this methods should be static,
+    virtual FederationManagementResult createFederationExecution(const std::string& federation, const std::string& objectModel);
+    virtual FederationManagementResult destroyFederationExecution(const std::string& federation);
 
     /// Join with federateName the federation execution federation
-    virtual bool join(const std::string& federateType, const std::string& federation);
+    virtual FederationManagementResult join(const std::string& federateType, const std::string& federation);
     virtual bool resign();
+    virtual bool getJoined() const;
 
     /// Synchronization Point handling
     virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag);
-    virtual bool waitForFederationSynchronizationPointAnnounced(const std::string& label);
+    virtual bool getFederationSynchronizationPointAnnounced(const std::string& label);
     virtual bool synchronizationPointAchieved(const std::string& label);
-    virtual bool waitForFederationSynchronized(const std::string& label);
+    virtual bool getFederationSynchronized(const std::string& label);
 
     /// Time management
     virtual bool enableTimeConstrained();
     virtual bool disableTimeConstrained();
+    virtual bool getTimeConstrainedEnabled();
 
     virtual bool enableTimeRegulation(const SGTimeStamp& lookahead);
     virtual bool disableTimeRegulation();
+    virtual bool modifyLookahead(const SGTimeStamp& timeStamp);
+    virtual bool getTimeRegulationEnabled();
 
-    virtual bool timeAdvanceRequestBy(const SGTimeStamp& dt);
-    virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime);
+    virtual bool timeAdvanceRequest(const SGTimeStamp& timeStamp);
+    virtual bool timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp);
+    virtual bool flushQueueRequest(const SGTimeStamp& timeStamp);
+    virtual bool getTimeAdvancePending();
+
+    virtual bool queryFederateTime(SGTimeStamp& timeStamp);
+    virtual bool queryLookahead(SGTimeStamp& timeStamp);
+    virtual bool queryGALT(SGTimeStamp& timeStamp);
+    virtual bool queryLITS(SGTimeStamp& timeStamp);
 
     /// Process messages
-    virtual bool tick();
-    virtual bool tick(const double& minimum, const double& maximum);
+    virtual bool processMessage();
+    virtual bool processMessages(const double& minimum, const double& maximum);
 
     virtual RTI13ObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass);
 
     virtual RTI13ObjectInstance* getObjectInstance(const std::string& name);
+    void insertObjectInstance(RTI13ObjectInstance* objectInstance);
 
 private:
     RTI13Federate(const RTI13Federate&);
@@ -74,13 +88,14 @@
 
     /// The federate handle
     RTI::FederateHandle _federateHandle;
-
-    /// The timeout for the single callback tick function in
-    /// syncronous operations that need to wait for a callback
-    double _tickTimeout;
+    bool _joined;
 
     /// RTI connection
     SGSharedPtr<RTI13Ambassador> _ambassador;
+
+    /// Callbacks from the rti are handled here.
+    struct FederateAmbassador;
+    FederateAmbassador* _federateAmbassador;
 };
 
 }

Modified: simgear/trunk/simgear/hla/RTI13ObjectClass.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTI13ObjectClass.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTI13ObjectClass.cxx (original)
+++ simgear/trunk/simgear/hla/RTI13ObjectClass.cxx Sun Jul 15 09:07:01 2012
@@ -37,12 +37,11 @@
 std::string
 RTI13ObjectClass::getName() const
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
+    if (!_ambassador.valid()) {
         SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
         return std::string();
     }
-    return ambassador->getObjectClassName(_handle);
+    return _ambassador->getObjectClassName(_handle);
 }
 
 unsigned
@@ -54,14 +53,13 @@
 unsigned
 RTI13ObjectClass::getAttributeIndex(const std::string& name) const
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return ~0u;
-    }
-
-    try {
-        RTI::AttributeHandle attributeHandle = ambassador->getAttributeHandle(name, _handle);
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return ~0u;
+    }
+
+    try {
+        RTI::AttributeHandle attributeHandle = _ambassador->getAttributeHandle(name, _handle);
 
         AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(attributeHandle);
         if (i !=  _attributeHandleIndexMap.end())
@@ -93,14 +91,13 @@
 unsigned
 RTI13ObjectClass::getOrCreateAttributeIndex(const std::string& name)
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return ~0u;
-    }
-
-    try {
-        RTI::AttributeHandle attributeHandle = ambassador->getAttributeHandle(name, _handle);
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return ~0u;
+    }
+
+    try {
+        RTI::AttributeHandle attributeHandle = _ambassador->getAttributeHandle(name, _handle);
 
         AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(attributeHandle);
         if (i !=  _attributeHandleIndexMap.end())
@@ -169,8 +166,7 @@
 bool
 RTI13ObjectClass::publish(const std::set<unsigned>& indexSet)
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
+    if (!_ambassador.valid()) {
         SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
         return false;
     }
@@ -185,7 +181,7 @@
             attributeHandleSet->add(_attributeHandleVector[*i]);
         }
 
-        ambassador->publishObjectClass(_handle, *attributeHandleSet);
+        _ambassador->publishObjectClass(_handle, *attributeHandleSet);
 
         for (unsigned i = 0; i < getNumAttributes(); ++i) {
             _attributeDataVector[i]._published = true;
@@ -225,14 +221,13 @@
 bool
 RTI13ObjectClass::unpublish()
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return false;
-    }
-
-    try {
-        ambassador->unpublishObjectClass(_handle);
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return false;
+    }
+
+    try {
+        _ambassador->unpublishObjectClass(_handle);
 
         for (unsigned i = 0; i < getNumAttributes(); ++i) {
             _attributeDataVector[i]._published = false;
@@ -272,8 +267,7 @@
 bool
 RTI13ObjectClass::subscribe(const std::set<unsigned>& indexSet, bool active)
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
+    if (!_ambassador.valid()) {
         SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
         return false;
     }
@@ -289,7 +283,7 @@
             attributeHandleSet->add(_attributeHandleVector[*i]);
         }
 
-        ambassador->subscribeObjectClassAttributes(_handle, *attributeHandleSet, active);
+        _ambassador->subscribeObjectClassAttributes(_handle, *attributeHandleSet, active);
 
         for (unsigned i = 0; i < getNumAttributes(); ++i) {
             _attributeDataVector[i]._subscribed = true;
@@ -326,14 +320,13 @@
 bool
 RTI13ObjectClass::unsubscribe()
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return 0;
-    }
-
-    try {
-        ambassador->unsubscribeObjectClass(_handle);
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return 0;
+    }
+
+    try {
+        _ambassador->unsubscribeObjectClass(_handle);
 
         for (unsigned i = 0; i < getNumAttributes(); ++i) {
             _attributeDataVector[i]._subscribed = false;
@@ -370,14 +363,22 @@
 RTIObjectInstance*
 RTI13ObjectClass::registerObjectInstance(HLAObjectInstance* hlaObjectInstance)
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return 0;
-    }
-
-    try {
-        return ambassador->registerObjectInstance(this, hlaObjectInstance);
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return 0;
+    }
+
+    SGSharedPtr<RTI13Federate> federate = _ambassador->_federate.lock();
+    if (!federate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Federate is zero.");
+        return 0;
+    }
+
+    try {
+        RTI::ObjectHandle objectHandle = _ambassador->registerObjectInstance(getHandle());
+        RTI13ObjectInstance* objectInstance = new RTI13ObjectInstance(objectHandle, hlaObjectInstance, this, _ambassador.get(), true);
+        federate->insertObjectInstance(objectInstance);
+        return objectInstance;
     } catch (RTI::ObjectClassNotDefined& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason);
         return 0;

Modified: simgear/trunk/simgear/hla/RTI13ObjectClass.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTI13ObjectClass.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTI13ObjectClass.hxx (original)
+++ simgear/trunk/simgear/hla/RTI13ObjectClass.hxx Sun Jul 15 09:07:01 2012
@@ -73,7 +73,7 @@
 
 private:
     RTI::ObjectClassHandle _handle;
-    SGWeakPtr<RTI13Ambassador> _ambassador;
+    SGSharedPtr<RTI13Ambassador> _ambassador;
 
     typedef std::map<RTI::AttributeHandle, unsigned> AttributeHandleIndexMap;
     AttributeHandleIndexMap _attributeHandleIndexMap;

Modified: simgear/trunk/simgear/hla/RTI13ObjectInstance.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTI13ObjectInstance.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTI13ObjectInstance.cxx (original)
+++ simgear/trunk/simgear/hla/RTI13ObjectInstance.cxx Sun Jul 15 09:07:01 2012
@@ -50,14 +50,13 @@
 std::string
 RTI13ObjectInstance::getName() const
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return std::string();
-    }
-
-    try {
-        return ambassador->getObjectInstanceName(_handle);
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return std::string();
+    }
+
+    try {
+        return _ambassador->getObjectInstanceName(_handle);
     } catch (RTI::ObjectNotKnown& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name: " << e._name << " " << e._reason);
         return std::string();
@@ -77,28 +76,21 @@
 }
 
 void
-RTI13ObjectInstance::addToRequestQueue()
-{
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return;
-    }
-
-    ambassador->addObjectInstanceForCallback(this);
-}
-
-void
 RTI13ObjectInstance::deleteObjectInstance(const RTIData& tag)
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return;
-    }
-
-    try {
-        ambassador->deleteObjectInstance(_handle, tag);
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    SGSharedPtr<RTI13Federate> federate = _ambassador->_federate.lock();
+    if (!federate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Federate is zero.");
+        return;
+    }
+
+    try {
+        _ambassador->deleteObjectInstance(_handle, tag);
     } catch (RTI::ObjectNotKnown& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
     } catch (RTI::DeletePrivilegeNotHeld& e) {
@@ -119,14 +111,19 @@
 void
 RTI13ObjectInstance::deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag)
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return;
-    }
-
-    try {
-        ambassador->deleteObjectInstance(_handle, timeStamp, tag);
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    SGSharedPtr<RTI13Federate> federate = _ambassador->_federate.lock();
+    if (!federate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Federate is zero.");
+        return;
+    }
+
+    try {
+        _ambassador->deleteObjectInstance(_handle, timeStamp, tag);
     } catch (RTI::ObjectNotKnown& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
     } catch (RTI::DeletePrivilegeNotHeld& e) {
@@ -149,14 +146,19 @@
 void
 RTI13ObjectInstance::localDeleteObjectInstance()
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
-        return;
-    }
-
-    try {
-        ambassador->localDeleteObjectInstance(_handle);
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return;
+    }
+
+    SGSharedPtr<RTI13Federate> federate = _ambassador->_federate.lock();
+    if (!federate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Federate is zero.");
+        return;
+    }
+
+    try {
+        _ambassador->localDeleteObjectInstance(_handle);
     } catch (RTI::ObjectNotKnown& e) {
         SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
     } catch (RTI::FederateOwnsAttributes& e) {
@@ -175,54 +177,62 @@
 }
 
 void
-RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag)
+RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag)
 {
     // Retrieve an empty update struct from the memory pool
-    UpdateList updateList;
-    getUpdateFromPool(updateList);
-
-    RTI::ULong numAttribs = attributeValuePairSet.size();
-    for (RTI::ULong i = 0; i < numAttribs; ++i) {
-        unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i));
+    RTIIndexDataPairList indexDataPairList;
+    for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
+         i != attributeHandleDataPairList.end(); ++i) {
+        unsigned index = getAttributeIndex(i->first);
         // Get a RTIData from the data pool
-        getDataFromPool(index, updateList.back()._indexDataPairList);
-        RTI::ULong length = attributeValuePairSet.getValueLength(i);
-        updateList.back()._indexDataPairList.back().second.resize(length);
-        attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length);
-        updateList.back()._tag = tag;
-    }
-
-    RTIObjectInstance::reflectAttributeValues(updateList.front()._indexDataPairList, tag);
+        getDataFromPool(indexDataPairList);
+        indexDataPairList.back().first = index;
+        indexDataPairList.back().second.swap(i->second);
+    }
+
+    RTIObjectInstance::reflectAttributeValues(indexDataPairList, tag);
+
+    RTIIndexDataPairList::iterator j = indexDataPairList.begin();
+    for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
+         i != attributeHandleDataPairList.end(); ++i, ++j) {
+        i->second.swap(j->second);
+    }
+
     // Return the update data back to the pool
-    putUpdateToPool(updateList);
-}
-
-void
-RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag)
+    putDataToPool(indexDataPairList);
+}
+
+void
+RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList,
+                                            const SGTimeStamp& timeStamp, const RTIData& tag)
 {
     // Retrieve an empty update struct from the memory pool
-    UpdateList updateList;
-    getUpdateFromPool(updateList);
-
-    RTI::ULong numAttribs = attributeValuePairSet.size();
-    for (RTI::ULong i = 0; i < numAttribs; ++i) {
-        unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i));
+    RTIIndexDataPairList indexDataPairList;
+    for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
+         i != attributeHandleDataPairList.end(); ++i) {
+        unsigned index = getAttributeIndex(i->first);
         // Get a RTIData from the data pool
-        getDataFromPool(index, updateList.back()._indexDataPairList);
-        RTI::ULong length = attributeValuePairSet.getValueLength(i);
-        updateList.back()._indexDataPairList.back().second.resize(length);
-        attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length);
-        updateList.back()._tag = tag;
-    }
-
-    scheduleUpdates(timeStamp, updateList);
+        getDataFromPool(indexDataPairList);
+        indexDataPairList.back().first = index;
+        indexDataPairList.back().second.swap(i->second);
+    }
+
+    RTIObjectInstance::reflectAttributeValues(indexDataPairList, timeStamp, tag);
+
+    RTIIndexDataPairList::iterator j = indexDataPairList.begin();
+    for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
+         i != attributeHandleDataPairList.end(); ++i, ++j) {
+        i->second.swap(j->second);
+    }
+
+    // Return the update data back to the pool
+    putDataToPool(indexDataPairList);
 }
 
 void
 RTI13ObjectInstance::requestObjectAttributeValueUpdate()
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
+    if (!_ambassador.valid()) {
         SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
         return;
     }
@@ -238,7 +248,7 @@
         if (!attributeHandleSet->size())
             return;
 
-        ambassador->requestObjectAttributeValueUpdate(_handle, *attributeHandleSet);
+        _ambassador->requestObjectAttributeValueUpdate(_handle, *attributeHandleSet);
 
         for (unsigned i = 0; i < numAttributes; ++i)
             setRequestAttributeUpdate(i, false);
@@ -272,12 +282,12 @@
 }
 
 void
-RTI13ObjectInstance::provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes)
+RTI13ObjectInstance::provideAttributeValueUpdate(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
 {
     // Called from the ambassador. Just marks some instance attributes dirty so that they are sent with the next update
-    RTI::ULong numAttribs = attributes.size();
+    size_t numAttribs = attributeHandleSet.size();
     for (RTI::ULong i = 0; i < numAttribs; ++i) {
-        unsigned index = getAttributeIndex(attributes.getHandle(i));
+        unsigned index = getAttributeIndex(attributeHandleSet[i]);
         setAttributeForceUpdate(index);
     }
 }
@@ -285,8 +295,7 @@
 void
 RTI13ObjectInstance::updateAttributeValues(const RTIData& tag)
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
+    if (!_ambassador.valid()) {
         SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
         return;
     }
@@ -312,28 +321,28 @@
         if (!_attributeValuePairSet->size())
             return;
 
-        ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, tag);
+        _ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, tag);
 
         for (unsigned i = 0; i < numAttributes; ++i) {
             setAttributeUpdated(i);
         }
 
     } catch (RTI::ObjectNotKnown& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
     } catch (RTI::AttributeNotDefined& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
     } catch (RTI::AttributeNotOwned& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::FederateNotExecutionMember& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::ConcurrentAccessAttempted& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::SaveInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::RestoreInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::RTIinternalError& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
     }
 
     // That means clear()
@@ -343,8 +352,7 @@
 void
 RTI13ObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
 {
-    SGSharedPtr<RTI13Ambassador> ambassador = _ambassador.lock();
-    if (!ambassador.valid()) {
+    if (!_ambassador.valid()) {
         SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
         return;
     }
@@ -370,30 +378,30 @@
         if (!_attributeValuePairSet->size())
             return;
 
-        ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, timeStamp, tag);
+        _ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, timeStamp, tag);
 
         for (unsigned i = 0; i < numAttributes; ++i) {
             setAttributeUpdated(i);
         }
 
     } catch (RTI::ObjectNotKnown& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
     } catch (RTI::AttributeNotDefined& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
     } catch (RTI::AttributeNotOwned& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
     } catch (RTI::InvalidFederationTime& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::FederateNotExecutionMember& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::ConcurrentAccessAttempted& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::SaveInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::RestoreInProgress& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
-    } catch (RTI::RTIinternalError& e) {
-        SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason);
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::FederateNotExecutionMember& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::ConcurrentAccessAttempted& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::SaveInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RestoreInProgress& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
+    } catch (RTI::RTIinternalError& e) {
+        SG_LOG(SG_NETWORK, SG_WARN, "RTI: could not update attribute values object instance: " << e._name << " " << e._reason);
     }
 
     // That means clear()
@@ -401,72 +409,72 @@
 }
 
 void
-RTI13ObjectInstance::attributesInScope(const RTI::AttributeHandleSet& attributeHandleSet)
-{
-    RTI::ULong numAttribs = attributeHandleSet.size();
+RTI13ObjectInstance::attributesInScope(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
+{
+    size_t numAttribs = attributeHandleSet.size();
     for (RTI::ULong i = 0; i < numAttribs; ++i) {
-        RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
+        RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
         setAttributeInScope(getAttributeIndex(attributeHandle), true);
     }
 }
 
 void
-RTI13ObjectInstance::attributesOutOfScope(const RTI::AttributeHandleSet& attributeHandleSet)
-{
-    RTI::ULong numAttribs = attributeHandleSet.size();
+RTI13ObjectInstance::attributesOutOfScope(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
+{
+    size_t numAttribs = attributeHandleSet.size();
     for (RTI::ULong i = 0; i < numAttribs; ++i) {
-        RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
+        RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
         setAttributeInScope(getAttributeIndex(attributeHandle), false);
     }
 }
 
 void
-RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet)
-{
-    RTI::ULong numAttribs = attributeHandleSet.size();
+RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
+{
+    size_t numAttribs = attributeHandleSet.size();
     for (RTI::ULong i = 0; i < numAttribs; ++i) {
-        RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
+        RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
         setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), true);
     }
 }
 
 void
-RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet)
-{
-    RTI::ULong numAttribs = attributeHandleSet.size();
+RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
+{
+    size_t numAttribs = attributeHandleSet.size();
     for (RTI::ULong i = 0; i < numAttribs; ++i) {
-        RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
+        RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
         setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), false);
     }
 }
 
 void
-RTI13ObjectInstance::requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag)
-{
-}
-
-void
-RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes)
-{
-}
-
-void
-RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes)
-{
-}
-
-void
-RTI13ObjectInstance::attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes)
-{
-}
-
-void
-RTI13ObjectInstance::requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag)
-{
-}
-
-void
-RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes)
+RTI13ObjectInstance::requestAttributeOwnershipAssumption(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag)
+{
+}
+
+void
+RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const std::vector<RTI::AttributeHandle>& attributes)
+{
+}
+
+void
+RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const std::vector<RTI::AttributeHandle>& attributes)
+{
+}
+
+void
+RTI13ObjectInstance::attributeOwnershipUnavailable(const std::vector<RTI::AttributeHandle>& attributes)
+{
+}
+
+void
+RTI13ObjectInstance::requestAttributeOwnershipRelease(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag)
+{
+}
+
+void
+RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const std::vector<RTI::AttributeHandle>& attributes)
 {
 }
 

Modified: simgear/trunk/simgear/hla/RTI13ObjectInstance.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTI13ObjectInstance.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTI13ObjectInstance.hxx (original)
+++ simgear/trunk/simgear/hla/RTI13ObjectInstance.hxx Sun Jul 15 09:07:01 2012
@@ -37,6 +37,9 @@
 class RTI13Ambassador;
 class RTI13ObjectClass;
 
+typedef std::pair<RTI::AttributeHandle, RTIData> RTI13AttributeHandleDataPair;
+typedef std::list<RTI13AttributeHandleDataPair> RTI13AttributeHandleDataPairList;
+
 class RTI13ObjectInstance : public RTIObjectInstance {
 public:
     RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned);
@@ -61,33 +64,31 @@
 
     virtual std::string getName() const;
 
-    virtual void addToRequestQueue();
-
     virtual void deleteObjectInstance(const RTIData& tag);
     virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag);
     virtual void localDeleteObjectInstance();
 
-    void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag);
-    void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag);
+    void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag);
+    void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
     virtual void requestObjectAttributeValueUpdate();
-    void provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes);
+    void provideAttributeValueUpdate(const std::vector<RTI::AttributeHandle>& attributes);
 
     virtual void updateAttributeValues(const RTIData& tag);
     virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag);
 
-    void attributesInScope(const RTI::AttributeHandleSet& attributes);
-    void attributesOutOfScope(const RTI::AttributeHandleSet& attributes);
+    void attributesInScope(const std::vector<RTI::AttributeHandle>& attributes);
+    void attributesOutOfScope(const std::vector<RTI::AttributeHandle>& attributes);
 
-    void turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributes);
-    void turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributes);
+    void turnUpdatesOnForObjectInstance(const std::vector<RTI::AttributeHandle>& attributes);
+    void turnUpdatesOffForObjectInstance(const std::vector<RTI::AttributeHandle>& attributes);
 
     // Not yet sure what to do here. But the dispatch functions are already there
-    void requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag);
-    void attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes);
-    void attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes);
-    void attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes);
-    void requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag);
-    void confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes);
+    void requestAttributeOwnershipAssumption(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag);
+    void attributeOwnershipDivestitureNotification(const std::vector<RTI::AttributeHandle>& attributes);
+    void attributeOwnershipAcquisitionNotification(const std::vector<RTI::AttributeHandle>& attributes);
+    void attributeOwnershipUnavailable(const std::vector<RTI::AttributeHandle>& attributes);
+    void requestAttributeOwnershipRelease(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag);
+    void confirmAttributeOwnershipAcquisitionCancellation(const std::vector<RTI::AttributeHandle>& attributes);
     void informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle);
     void attributeIsNotOwned(RTI::AttributeHandle attributeHandle);
     void attributeOwnedByRTI(RTI::AttributeHandle attributeHandle);
@@ -95,7 +96,7 @@
 private:
     RTI::ObjectHandle _handle;
     SGSharedPtr<const RTI13ObjectClass> _objectClass;
-    SGWeakPtr<RTI13Ambassador> _ambassador;
+    SGSharedPtr<RTI13Ambassador> _ambassador;
 
     // cached storage for updates
     std::auto_ptr<RTI::AttributeHandleValuePairSet> _attributeValuePairSet;

Modified: simgear/trunk/simgear/hla/RTIData.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTIData.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTIData.hxx (original)
+++ simgear/trunk/simgear/hla/RTIData.hxx Sun Jul 15 09:07:01 2012
@@ -115,6 +115,13 @@
         ensureCapacity(capacity);
     }
 
+    void swap(RTIData& data)
+    {
+        std::swap(_data, data._data);
+        std::swap(_size, data._size);
+        std::swap(_capacity, data._capacity);
+    }
+
     void setData(char* data, unsigned size)
     {
         if (_capacity)

Modified: simgear/trunk/simgear/hla/RTIFederate.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTIFederate.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTIFederate.hxx (original)
+++ simgear/trunk/simgear/hla/RTIFederate.hxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2010  Mathias Froehlich - Mathias.Froehlich at web.de
+// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich at web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
@@ -32,63 +32,60 @@
     RTIFederate();
     virtual ~RTIFederate();
 
-    /// Get the name of the joined federate/federation
-    const std::string& getFederateType() const
-    { return _federateType; }
-    const std::string& getFederationName() const
-    { return _federationName; }
-
     /// Create a federation execution
     /// Semantically this methods should be static,
-    /// but the nonstatic case could reuse the connection to the server
-    /// FIXME: cannot determine from the return value if we created the execution
-    virtual bool createFederationExecution(const std::string& federation, const std::string& objectModel) = 0;
-    virtual bool destroyFederationExecution(const std::string& federation) = 0;
+    enum FederationManagementResult {
+        FederationManagementSuccess,
+        FederationManagementFail,
+        FederationManagementFatal
+    };
+
+    virtual FederationManagementResult createFederationExecution(const std::string& federation, const std::string& objectModel) = 0;
+    virtual FederationManagementResult destroyFederationExecution(const std::string& federation) = 0;
 
     /// Join with federateName the federation execution federation
-    virtual bool join(const std::string& federateType, const std::string& federation) = 0;
+    virtual FederationManagementResult join(const std::string& federateType, const std::string& federation) = 0;
     virtual bool resign() = 0;
+    virtual bool getJoined() const = 0;
 
     /// Synchronization Point handling
     virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag) = 0;
-    virtual bool waitForFederationSynchronizationPointAnnounced(const std::string& label) = 0;
+    virtual bool getFederationSynchronizationPointAnnounced(const std::string& label) = 0;
     virtual bool synchronizationPointAchieved(const std::string& label) = 0;
-    virtual bool waitForFederationSynchronized(const std::string& label) = 0;
+    virtual bool getFederationSynchronized(const std::string& label) = 0;
 
     /// Time management
     virtual bool enableTimeConstrained() = 0;
     virtual bool disableTimeConstrained() = 0;
+    virtual bool getTimeConstrainedEnabled() = 0;
 
     virtual bool enableTimeRegulation(const SGTimeStamp& lookahead) = 0;
     virtual bool disableTimeRegulation() = 0;
+    virtual bool modifyLookahead(const SGTimeStamp& timeStamp) = 0;
+    virtual bool getTimeRegulationEnabled() = 0;
 
-    virtual bool timeAdvanceRequestBy(const SGTimeStamp& dt) = 0;
     virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime) = 0;
+    virtual bool timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp) = 0;
+    virtual bool flushQueueRequest(const SGTimeStamp& timeStamp) = 0;
+    virtual bool getTimeAdvancePending() = 0;
+
+    virtual bool queryFederateTime(SGTimeStamp& timeStamp) = 0;
+    virtual bool queryLookahead(SGTimeStamp& timeStamp) = 0;
+    virtual bool queryGALT(SGTimeStamp& timeStamp) = 0;
+    virtual bool queryLITS(SGTimeStamp& timeStamp) = 0;
 
     /// Process messages
-    virtual bool tick() = 0;
-    virtual bool tick(const double& minimum, const double& maximum) = 0;
+    virtual bool processMessage() = 0;
+    virtual bool processMessages(const double& minimum, const double& maximum) = 0;
 
     virtual RTIObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass) = 0;
     // virtual RTIInteractionClass* createInteractionClass(const std::string& name) = 0;
 
     virtual RTIObjectInstance* getObjectInstance(const std::string& name) = 0;
 
-protected:
-    void setFederateType(const std::string& federateType)
-    { _federateType = federateType; }
-    void setFederationName(const std::string& federationName)
-    { _federationName = federationName; }
-
 private:
     RTIFederate(const RTIFederate&);
     RTIFederate& operator=(const RTIFederate&);
-
-    /// The federates name
-    std::string _federateType;
-
-    /// The federation execution name
-    std::string _federationName;
 };
 
 }

Modified: simgear/trunk/simgear/hla/RTIObjectClass.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTIObjectClass.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTIObjectClass.cxx (original)
+++ simgear/trunk/simgear/hla/RTIObjectClass.cxx Sun Jul 15 09:07:01 2012
@@ -39,6 +39,7 @@
         return;
     }
     hlaObjectClass->discoverInstance(objectInstance, tag);
+    objectInstance->requestObjectAttributeValueUpdate();
 }
 
 void

Modified: simgear/trunk/simgear/hla/RTIObjectInstance.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/hla/RTIObjectInstance.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/hla/RTIObjectInstance.hxx (original)
+++ simgear/trunk/simgear/hla/RTIObjectInstance.hxx Sun Jul 15 09:07:01 2012
@@ -50,9 +50,6 @@
     unsigned getAttributeIndex(const std::string& name) const;
     std::string getAttributeName(unsigned index) const;
 
-    // FIXME: factor out an ambassador base
-    virtual void addToRequestQueue() = 0;
-
     virtual void deleteObjectInstance(const RTIData& tag) = 0;
     virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
     virtual void localDeleteObjectInstance() = 0;
@@ -63,20 +60,6 @@
     virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
 
     void removeInstance(const RTIData& tag);
-    // Call this if you want to roll up the queued timestamed updates
-    // and reflect that into the attached data elements.
-    void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
-    {
-        // replay all updates up to the given timestamp
-        UpdateListMap::iterator last = _updateListMap.upper_bound(timeStamp);
-        for (UpdateListMap::iterator i = _updateListMap.begin(); i != last; ++i) {
-            for (UpdateList::iterator j = i->second.begin(); j != i->second.end(); ++j) {
-                // FIXME have a variant that takes the timestamp?
-                reflectAttributeValues(j->_indexDataPairList, j->_tag);
-            }
-            putUpdateToPool(i->second);
-        }
-    }
     void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);
     void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
     void reflectAttributeValue(unsigned i, const RTIData& data)
@@ -136,6 +119,8 @@
             } else {
                 _attributeData[i].setUpdateEnabled(false);
                 _attributeData[i].setOwned(false);
+                if (getAttributeSubscribed(i))
+                    _attributeData[i].setRequestUpdate(true);
             }
         }
         _attributeData.resize(numAttributes);
@@ -143,9 +128,13 @@
             if (getAttributePublished(i)) {
                 _attributeData[i].setUpdateEnabled(true);
                 _attributeData[i].setOwned(owned);
+                if (!owned && getAttributeSubscribed(i))
+                    _attributeData[i].setRequestUpdate(true);
             } else {
                 _attributeData[i].setUpdateEnabled(false);
                 _attributeData[i].setOwned(false);
+                if (getAttributeSubscribed(i))
+                    _attributeData[i].setRequestUpdate(true);
             }
         }
     }
@@ -213,7 +202,6 @@
         if (request) {
             if (!_pendingAttributeUpdateRequest) {
                 _pendingAttributeUpdateRequest = true;
-                addToRequestQueue();
             }
         }
     }
@@ -239,80 +227,25 @@
     // Is true if we should emit a requestattr
     bool _pendingAttributeUpdateRequest;
 
-    // Contains a full update as it came in from the RTI
-    struct Update {
-        RTIIndexDataPairList _indexDataPairList;
-        RTIData _tag;
-    };
-    // A bunch of updates for the same timestamp
-    typedef std::list<Update> UpdateList;
-    // The timestamp sorted list of updates
-    typedef std::map<SGTimeStamp, UpdateList> UpdateListMap;
-
-    // The timestamped updates sorted by timestamp
-    UpdateListMap _updateListMap;
-
-    // The pool of unused updates so that we do not need to malloc/free each time
-    UpdateList _updateList;
-
-    void getUpdateFromPool(UpdateList& updateList)
-    {
-        if (_updateList.empty())
-            updateList.push_back(Update());
-        else
-            updateList.splice(updateList.end(), _updateList, _updateList.begin());
-    }
-    void putUpdateToPool(UpdateList& updateList)
-    {
-        for (UpdateList::iterator i = updateList.begin(); i != updateList.end(); ++i)
-            putDataToPool(i->_indexDataPairList);
-        _updateList.splice(_updateList.end(), updateList);
-    }
-
-    // Appends the updates in the list to the given timestamps updates
-    void scheduleUpdates(const SGTimeStamp& timeStamp, UpdateList& updateList)
-    {
-        UpdateListMap::iterator i = _updateListMap.find(timeStamp);
-        if (i == _updateListMap.end())
-            i = _updateListMap.insert(UpdateListMap::value_type(timeStamp, UpdateList())).first;
-        i->second.splice(i->second.end(), updateList);
-    }
+    // Pool of update list entries
+    RTIIndexDataPairList _indexDataPairList;
 
     // This adds raw storage for attribute index i to the end of the dataPairList.
-    void getDataFromPool(unsigned i, RTIIndexDataPairList& dataPairList)
-    {
-        if (_attributeData.size() <= i) {
-            SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
-            return;
-        }
-
+    void getDataFromPool(RTIIndexDataPairList& dataPairList)
+    {
         // Nothing left in the pool - so allocate something
-        if (_attributeData[i]._indexDataPairList.empty()) {
+        if (_indexDataPairList.empty()) {
             dataPairList.push_back(RTIIndexDataPairList::value_type());
-            dataPairList.back().first = i;
             return;
         }
 
         // Take one from the pool
-        dataPairList.splice(dataPairList.end(),
-                            _attributeData[i]._indexDataPairList,
-                            _attributeData[i]._indexDataPairList.begin());
+        dataPairList.splice(dataPairList.end(), _indexDataPairList, _indexDataPairList.begin());
     }
 
     void putDataToPool(RTIIndexDataPairList& dataPairList)
     {
-        while (!dataPairList.empty()) {
-            // Put back into the pool
-            unsigned i = dataPairList.front().first;
-            if (_attributeData.size() <= i) {
-                // should not happen!!!
-                SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
-                dataPairList.pop_front();
-            } else {
-                _attributeData[i]._indexDataPairList.splice(_attributeData[i]._indexDataPairList.begin(),
-                                                            dataPairList, dataPairList.begin());
-            }
-        }
+        _indexDataPairList.splice(_indexDataPairList.begin(), dataPairList);
     }
 
     struct AttributeData {

Modified: simgear/trunk/simgear/io/decode_binobj.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/decode_binobj.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/decode_binobj.cxx (original)
+++ simgear/trunk/simgear/io/decode_binobj.cxx Sun Jul 15 09:07:01 2012
@@ -4,9 +4,13 @@
 
 #include <simgear/compiler.h>
 
+#ifndef _WIN32
 #include <unistd.h>
+#endif
+
 #include <iostream>
 #include <cstdlib>
+#include <cstdio>
 
 #include "sg_binobj.hxx"
 

Modified: simgear/trunk/simgear/io/iochannel.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/iochannel.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/iochannel.cxx (original)
+++ simgear/trunk/simgear/io/iochannel.cxx Sun Jul 15 09:07:01 2012
@@ -73,6 +73,6 @@
 
 
 // dummy eof routine
-bool SGIOChannel::eof() {
+bool SGIOChannel::eof() const {
     return false;
 }

Modified: simgear/trunk/simgear/io/iochannel.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/iochannel.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/iochannel.hxx (original)
+++ simgear/trunk/simgear/io/iochannel.hxx Sun Jul 15 09:07:01 2012
@@ -29,15 +29,6 @@
 
 
 #include <simgear/compiler.h>
-
-// #include "protocol.hxx"
-
-#include <string>
-#include <vector>
-
-using std::vector;
-using std::string;
-
 
 #define SG_IO_MAX_MSG_SIZE 16384
 
@@ -158,7 +149,7 @@
      * false.
      * @return result of eof check
      */
-    virtual bool eof();
+    virtual bool eof() const;
 
     inline void set_type( SGChannelType t ) { type = t; }
     inline SGChannelType get_type() const { return type; }

Modified: simgear/trunk/simgear/io/raw_socket.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/raw_socket.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/raw_socket.cxx (original)
+++ simgear/trunk/simgear/io/raw_socket.cxx Sun Jul 15 09:07:01 2012
@@ -1,20 +1,20 @@
 /*
      simgear::Socket, adapted from PLIB Socket by James Turner
      Copyright (C) 2010  James Turner
-     
+
      PLIB - A Suite of Portable Game Libraries
      Copyright (C) 1998,2002  Steve Baker
- 
+
      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 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
@@ -25,8 +25,7 @@
 #endif
 
 #include <simgear/compiler.h>
-
-#include "sg_socket.hxx"
+#include "raw_socket.hxx"
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 # define WINSOCK // use winsock convetions, otherwise standard POSIX
@@ -37,16 +36,18 @@
 #include <cstring>
 #include <cassert>
 #include <cstdio> // for snprintf
+#include <errno.h>
 
 #if defined(WINSOCK)
-#  include <winsock.h>
+#  include <winsock2.h>
+#  include <ws2tcpip.h>
 #  include <stdarg.h>
 #else
 #  include <sys/types.h>
 #  include <sys/socket.h>
 #  include <netinet/in.h>
 #  include <arpa/inet.h>
-#  include <sys/time.h>  
+#  include <sys/time.h>
 #  include <unistd.h>
 #  include <netdb.h>
 #  include <fcntl.h>
@@ -56,55 +57,253 @@
 #define socklen_t int
 #endif
 
+#include <map>
+
 #include <simgear/debug/logstream.hxx>
 #include <simgear/structure/exception.hxx>
+#include <simgear/threads/SGThread.hxx>
+
+namespace {
+
+class Resolver : public SGThread
+{
+public:
+    static Resolver* instance()
+    {
+        if (!static_instance) {
+            static_instance = new Resolver;
+            atexit(&Resolver::cleanup);
+            static_instance->start();
+        }
+
+        return static_instance;
+    }
+
+    static void cleanup()
+    {
+        static_instance->shutdown();
+        static_instance->join();
+    }
+
+    Resolver() :
+        _done(false)
+    {
+    }
+
+    void shutdown()
+    {
+        _lock.lock();
+        _done = true;
+        _wait.signal();
+        _lock.unlock();
+    }
+
+    simgear::IPAddress* lookup(const string& host)
+    {
+        simgear::IPAddress* result = NULL;
+        _lock.lock();
+        AddressCache::iterator it = _cache.find(host);
+        if (it == _cache.end()) {
+            _cache[host] = NULL; // mark as needing looked up
+            _wait.signal(); // if the thread was sleeping, poke it
+        } else {
+            result = it->second;
+        }
+        _lock.unlock();
+        return result;
+    }
+
+    simgear::IPAddress* lookupSync(const string& host)
+    {
+        simgear::IPAddress* result = NULL;
+        _lock.lock();
+        AddressCache::iterator it = _cache.find(host);
+        if (it == _cache.end()) {
+            _lock.unlock();
+            result = new simgear::IPAddress;
+            bool ok = lookupHost(host.c_str(), *result);
+            _lock.lock();
+            if (ok) {
+                _cache[host] = result; // mark as needing looked up
+            } else {
+                delete result;
+                result = NULL;
+            }
+        } else { // found in cache, easy
+            result = it->second;
+        }
+        _lock.unlock();
+        return result;
+    }
+protected:
+    /**
+     * run method waits on a condition (_wait), and when awoken,
+     * finds any unresolved entries in _cache, resolves them, and goes
+     * back to sleep.
+     */
+    virtual void run()
+    {
+        _lock.lock();
+        while (!_done) {
+            AddressCache::iterator it;
+
+            for (it = _cache.begin(); it != _cache.end(); ++it) {
+                if (it->second == NULL) {
+                    string h = it->first;
+
+                    _lock.unlock();
+                    simgear::IPAddress* addr = new simgear::IPAddress;
+                // may take seconds or even minutes!
+                    lookupHost(h.c_str(), *addr);
+                    _lock.lock();
+
+                // cahce may have changed while we had the lock released -
+                // so iterators may be invalid: restart the traversal
+                    it = _cache.begin();
+                    _cache[h] = addr;
+                } // of found un-resolved entry
+            } // of un-resolved address iteration
+            _wait.wait(_lock);
+        } // of thread run loop
+        _lock.unlock();
+    }
+private:
+    static Resolver* static_instance;
+
+    /**
+     * The actual synchronous, blocking host lookup function
+     * do *not* call this with any locks (mutexs) held, since depending
+     * on local system configuration / network availability, it
+     * may block for seconds or minutes.
+     */
+    bool lookupHost(const char* host, simgear::IPAddress& addr)
+    {
+      struct addrinfo hints;
+      memset(&hints, 0, sizeof(struct addrinfo));
+      hints.ai_family = AF_INET;
+      bool ok = false;
+
+      struct addrinfo* result0 = NULL;
+      int err = getaddrinfo(host, NULL, &hints, &result0);
+      if (err) {
+        SG_LOG(SG_IO, SG_WARN, "getaddrinfo failed for '" << host << "' : " << gai_strerror(err));
+        return false;
+      } else {
+          struct addrinfo* result;
+          for (result = result0; result != NULL; result = result->ai_next) {
+              if (result->ai_family != AF_INET) { // only accept IP4 for the moment
+                  continue;
+              }
+
+              if (result->ai_addrlen != addr.getAddrLen()) {
+                  SG_LOG(SG_IO, SG_ALERT, "mismatch in socket address sizes: got " <<
+                      result->ai_addrlen << ", expected " << addr.getAddrLen());
+                  continue;
+              }
+
+              memcpy(addr.getAddr(), result->ai_addr, result->ai_addrlen);
+              ok = true;
+              break;
+          } // of getaddrinfo results iteration
+      } // of getaddrinfo succeeded
+
+      freeaddrinfo(result0);
+      return ok;
+    }
+
+    SGMutex _lock;
+    SGWaitCondition _wait;
+
+    typedef std::map<string, simgear::IPAddress*> AddressCache;
+    AddressCache _cache;
+    bool _done;
+};
+
+Resolver* Resolver::static_instance = NULL;
+
+} // of anonymous namespace
 
 namespace simgear
 {
-                                                                                       
+
 IPAddress::IPAddress ( const char* host, int port )
 {
   set ( host, port ) ;
 }
 
+IPAddress::IPAddress( const IPAddress& other ) :
+  addr(NULL)
+{
+  if (other.addr) {
+    addr = (struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
+    memcpy(addr, other.addr, sizeof(struct sockaddr_in));
+  }
+}
+
+const IPAddress& IPAddress::operator=(const IPAddress& other)
+{
+  if (addr) {
+    free(addr);
+    addr = NULL;
+  }
+
+  if (other.addr) {
+    addr = (struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
+    memcpy(addr, other.addr, sizeof(struct sockaddr_in));
+  }
+
+  return *this;
+}
 
 void IPAddress::set ( const char* host, int port )
 {
-  memset(this, 0, sizeof(IPAddress));
-
-  sin_family = AF_INET ;
-  sin_port = htons (port);
+  addr = (struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
+  memset(addr, 0, sizeof(struct sockaddr_in));
+
+  addr->sin_family = AF_INET ;
+  addr->sin_port = htons (port);
 
   /* Convert a string specifying a host name or one of a few symbolic
-  ** names to a numeric IP address.  This usually calls gethostbyname()
+  ** names to a numeric IP address.  This usually calls getaddrinfo()
   ** to do the work; the names "" and "<broadcast>" are special.
   */
 
   if (!host || host[0] == '\0') {
-    sin_addr = INADDR_ANY;
+    addr->sin_addr.s_addr = INADDR_ANY;
     return;
   }
-  
+
   if (strcmp(host, "<broadcast>") == 0) {
-    sin_addr = INADDR_BROADCAST;
+    addr->sin_addr.s_addr = INADDR_BROADCAST;
     return;
   }
-  
-  sin_addr = inet_addr ( host ) ;
-  if (sin_addr != INADDR_NONE) {
-    return;
-  }
-// finally, try gethostbyname
-    struct hostent *hp = gethostbyname ( host ) ;
-    if (!hp) {
-      SG_LOG(SG_IO, SG_WARN, "gethostbyname failed for " << host);
-      sin_addr = INADDR_ANY ;
-      return;
-    }
-    
-    memcpy ( (char *) &sin_addr, hp->h_addr, hp->h_length ) ;
-}
-
+
+// check the cache
+  IPAddress* cached = Resolver::instance()->lookupSync(host);
+  if (cached) {
+      memcpy(addr, cached->getAddr(), cached->getAddrLen());
+  }
+
+  addr->sin_port = htons (port); // fix up port after getaddrinfo
+}
+
+IPAddress::~IPAddress()
+{
+  if (addr) {
+    free (addr);
+  }
+}
+
+bool IPAddress::lookupNonblocking(const char* host, IPAddress& addr)
+{
+    IPAddress* cached = Resolver::instance()->lookup(host);
+    if (!cached) {
+        return false;
+    }
+
+    addr = *cached;
+    return true;
+}
 
 /* Create a string object representing an IP address.
    This is always a string of the form 'dd.dd.dd.dd' (with variable
@@ -112,31 +311,52 @@
 
 const char* IPAddress::getHost () const
 {
-#if 0
-  const char* buf = inet_ntoa ( sin_addr ) ;
-#else
+    if (!addr) {
+        return NULL;
+    }
+    
   static char buf [32];
-	long x = ntohl(sin_addr);
+	long x = ntohl(addr->sin_addr.s_addr);
 	sprintf(buf, "%d.%d.%d.%d",
 		(int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
 		(int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff );
-#endif
   return buf;
 }
 
-unsigned int IPAddress::getIP () const 
-{ 
-	return sin_addr; 
+unsigned int IPAddress::getIP () const
+{
+    if (!addr) {
+        return 0;
+    }
+    
+	return addr->sin_addr.s_addr;
 }
 
 unsigned int IPAddress::getPort() const
 {
-  return ntohs(sin_port);
-}
-
-unsigned int IPAddress::getFamily () const 
-{ 
-	return sin_family; 
+    if (!addr) {
+        return 0;
+    }
+    
+  return ntohs(addr->sin_port);
+}
+
+void IPAddress::setPort(int port)
+{
+    if (!addr) {
+        return;
+    }
+    
+    addr->sin_port = htons(port);
+}
+
+unsigned int IPAddress::getFamily () const
+{
+    if (!addr) {
+        return 0;
+    }
+    
+	return addr->sin_family;
 }
 
 const char* IPAddress::getLocalHost ()
@@ -163,9 +383,32 @@
 
 bool IPAddress::getBroadcast () const
 {
-  return sin_addr == INADDR_BROADCAST;
-}
-
+    if (!addr) {
+        return false;
+    }
+    
+    return (addr->sin_addr.s_addr == INADDR_BROADCAST);
+}
+
+unsigned int IPAddress::getAddrLen() const
+{
+    return sizeof(struct sockaddr_in);
+}
+
+struct sockaddr* IPAddress::getAddr() const
+{
+    if (addr == NULL) {
+        addr = (struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
+        memset(addr, 0, sizeof(struct sockaddr_in));
+    }
+
+    return (struct sockaddr*) addr;
+}
+
+bool IPAddress::isValid() const
+{
+    return (addr != NULL);
+}
 
 Socket::Socket ()
 {
@@ -248,7 +491,7 @@
   } else {
       result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, NULL, 0 );
   }
-  
+
   if ( result < 0 ) {
       throw sg_exception("Socket::setBroadcast failed");
   }
@@ -262,13 +505,13 @@
   IPAddress addr ( host, port ) ;
 
 #if !defined(WINSOCK)
-  if( (result = ::bind(handle,(const sockaddr*)&addr,sizeof(IPAddress))) < 0 ) {
-    SG_LOG(SG_IO, SG_ALERT, "bind(" << host << ":" << port << ") failed. Errno " << errno << " (" << strerror(errno) << ")");
+  if( (result = ::bind(handle, addr.getAddr(), addr.getAddrLen() ) ) < 0 ) {
+    SG_LOG(SG_IO, SG_ALERT, "bind(" << addr.getHost() << ":" << addr.getPort() << ") failed. Errno " << errno << " (" << strerror(errno) << ")");
     return result;
   }
 #endif
 
-  // 224.0.0.0 - 239.255.255.255 are multicast   
+  // 224.0.0.0 - 239.255.255.255 are multicast
   // Usage of 239.x.x.x is recommended for local scope
   // Reference: http://tools.ietf.org/html/rfc5771
   if( ntohl(addr.getIP()) >= 0xe0000000 && ntohl(addr.getIP()) <= 0xefffffff ) {
@@ -278,7 +521,7 @@
     a.sin_addr.S_un.S_addr = INADDR_ANY;
     a.sin_family = AF_INET;
     a.sin_port = htons(port);
-      
+
     if( (result = ::bind(handle,(const sockaddr*)&a,sizeof(a))) < 0 ) {
       SG_LOG(SG_IO, SG_ALERT, "bind(any:" << port << ") failed. Errno " << errno << " (" << strerror(errno) << ")");
       return result;
@@ -294,7 +537,7 @@
     }
   }
 #if defined(WINSOCK)
-  else if( (result = ::bind(handle,(const sockaddr*)&addr,sizeof(IPAddress))) < 0 ) {
+  else if( (result = ::bind(handle,addr.getAddr(), addr.getAddrLen())) < 0 ) {
     SG_LOG(SG_IO, SG_ALERT, "bind(" << host << ":" << port << ") failed. Errno " << errno << " (" << strerror(errno) << ")");
     return result;
   }
@@ -321,20 +564,26 @@
   }
   else
   {
-    socklen_t addr_len = (socklen_t) sizeof(IPAddress) ;
-    return ::accept(handle,(sockaddr*)addr,&addr_len);
+    socklen_t addr_len = addr->getAddrLen(); ;
+    return ::accept(handle, addr->getAddr(), &addr_len);
   }
 }
 
 
 int Socket::connect ( const char* host, int port )
 {
-  assert ( handle != -1 ) ;
   IPAddress addr ( host, port ) ;
-  if ( addr.getBroadcast() ) {
+  return connect ( &addr );
+}
+
+
+int Socket::connect ( IPAddress* addr )
+{
+  assert ( handle != -1 ) ;
+  if ( addr->getBroadcast() ) {
       setBroadcast( true );
   }
-  return ::connect(handle,(const sockaddr*)&addr,sizeof(IPAddress));
+  return ::connect(handle, addr->getAddr(), addr->getAddrLen() );
 }
 
 
@@ -350,7 +599,7 @@
 {
   assert ( handle != -1 ) ;
   return ::sendto(handle,(const char*)buffer,size,flags,
-                         (const sockaddr*)to,sizeof(IPAddress));
+                         (const sockaddr*) to->getAddr(), to->getAddrLen());
 }
 
 
@@ -365,8 +614,8 @@
                           int flags, IPAddress* from )
 {
   assert ( handle != -1 ) ;
-  socklen_t fromlen = (socklen_t) sizeof(IPAddress) ;
-  return ::recvfrom(handle,(char*)buffer,size,flags,(sockaddr*)from,&fromlen);
+  socklen_t fromlen = (socklen_t) from->getAddrLen() ;
+  return ::recvfrom(handle,(char*)buffer,size,flags, from->getAddr(),&fromlen);
 }
 
 
@@ -422,7 +671,7 @@
 {
   fd_set r,w;
   int	retval;
-  
+
   FD_ZERO (&r);
   FD_ZERO (&w);
 
@@ -460,7 +709,7 @@
   // It bothers me that select()'s first argument does not appear to
   // work as advertised... [it hangs like this if called with
   // anything less than FD_SETSIZE, which seems wasteful?]
-  
+
   // Note: we ignore the 'exception' fd_set - I have never had a
   // need to use it.  The name is somewhat misleading - the only
   // thing I have ever seen it used for is to detect urgent data -
@@ -526,8 +775,6 @@
 
 int Socket::initSockets()
 {
-  assert ( sizeof(sockaddr_in) == sizeof(IPAddress) ) ;
-
 #if defined(WINSOCK)
 	/* Start up the windows networking */
 	WORD version_wanted = MAKEWORD(1,1);

Modified: simgear/trunk/simgear/io/raw_socket.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/raw_socket.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/raw_socket.hxx (original)
+++ simgear/trunk/simgear/io/raw_socket.hxx Sun Jul 15 09:07:01 2012
@@ -23,12 +23,15 @@
 #ifndef SG_IO_SOCKET_HXX
 #define SG_IO_SOCKET_HXX
 
-#include <errno.h>
+//#include <errno.h>
 
-#if defined(__APPLE__) || defined(__FreeBSD__)
-#  include <netinet/in.h>
-#endif
+//#if defined(__APPLE__) || defined(__FreeBSD__)
+//#  include <netinet/in.h>
+//#endif
 
+struct sockaddr_in;
+struct sockaddr;
+     
 namespace simgear
 {
 
@@ -37,32 +40,31 @@
  */
 class IPAddress
 {
-  /* DANGER!!!  This MUST match 'struct sockaddr_in' exactly! */
-#if defined(__APPLE__) || defined(__FreeBSD__)
-  __uint8_t      sin_len;
-  __uint8_t      sin_family;
-  in_port_t      sin_port;
-  in_addr_t      sin_addr;
-  char           sin_zero[8];
-#else
-  short          sin_family     ;
-  unsigned short sin_port       ;
-  unsigned int   sin_addr       ;
-  char           sin_zero [ 8 ] ;
-#endif
+    mutable struct sockaddr_in* addr;
+public:
+  IPAddress () : addr(0) {}
+  IPAddress ( const char* host, int port ) ;
+  ~IPAddress();
+  
+  static bool lookupNonblocking(const char* host, IPAddress& addr);
+  
+  IPAddress( const IPAddress& other );
+  const IPAddress& operator=(const IPAddress& other);
 
-public:
-  IPAddress () {}
-  IPAddress ( const char* host, int port ) ;
-
+  bool isValid () const;
   void set ( const char* host, int port ) ;
   const char* getHost () const ;
   unsigned int getPort() const ;
+  void setPort(int port);
+  
   unsigned int getIP () const ;
   unsigned int getFamily () const ;
   static const char* getLocalHost () ;
 
   bool getBroadcast () const ;
+  
+  unsigned int getAddrLen() const;
+  sockaddr* getAddr() const;
 };
 
 
@@ -72,7 +74,7 @@
 class Socket
 {
   int handle ;
-
+  
 public:
   
   Socket () ;
@@ -89,6 +91,7 @@
   int   listen	    ( int backlog ) ;
   int   accept      ( IPAddress* addr ) ;
   int   connect     ( const char* host, int port ) ;
+  int   connect     ( IPAddress* addr ) ;
   int   send	    ( const void * buffer, int size, int flags = 0 ) ;
   int   sendto      ( const void * buffer, int size, int flags, const IPAddress* to ) ;
   int   recv	    ( void * buffer, int size, int flags = 0 ) ;

Modified: simgear/trunk/simgear/io/sg_binobj.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_binobj.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_binobj.cxx (original)
+++ simgear/trunk/simgear/io/sg_binobj.cxx Sun Jul 15 09:07:01 2012
@@ -33,10 +33,12 @@
 #include <time.h>
 #include <cstring>
 #include <cstdlib> // for system()
+#include <cassert>
 
 #include <vector>
 #include <string>
 #include <iostream>
+#include <bitset>
 
 #include <simgear/bucket/newbucket.hxx>
 #include <simgear/misc/sg_path.hxx>
@@ -85,163 +87,282 @@
 
     char *ptr;
     unsigned int size;
-
+    size_t offset;
 public:
 
-    inline sgSimpleBuffer( unsigned int s )
+    sgSimpleBuffer( unsigned int s = 0) :
+        ptr(NULL),
+        size(0),
+        offset(0)
     {
-	size = 1;
-	while ( size < s ) {
-	    size *= 2;
-	}
-        SG_LOG(SG_EVENT, SG_DEBUG, "Creating a new buffer of size = " << size);
-	ptr = new char[size];
-    }
-
-    inline ~sgSimpleBuffer() {
-	delete [] ptr;
-    }
-
-    inline unsigned int get_size() const { return size; }
-    inline char *get_ptr() const { return ptr; }
-    inline void resize( unsigned int s ) {
-	if ( s > size ) {
-	    if ( ptr != NULL ) {
-		delete [] ptr;
-	    }
-	    while ( size < s ) {
-		size *= 2;
-	    }
-            SG_LOG(SG_EVENT, SG_DEBUG, "resizing buffer to size = " << size);
-	    ptr = new char[size];
-	}
+        resize(s);
+    }
+
+    ~sgSimpleBuffer()
+    {
+        delete [] ptr;
+    }
+
+    unsigned int get_size() const { return size; }
+    char *get_ptr() const { return ptr; }
+    
+    void reset()
+    {
+        offset = 0;
+    }
+    
+    void resize( unsigned int s )
+    {
+        if ( s > size ) {
+            if ( ptr != NULL ) {
+                delete [] ptr;
+            }
+          
+            if ( size == 0) {
+                size = 16;
+            }
+          
+            while ( size < s ) {
+              size = size << 1;
+            }
+            ptr = new char[size];
+        }
+    }
+    
+    SGVec3d readVec3d()
+    {
+        double* p = reinterpret_cast<double*>(ptr + offset);
+        
+        if ( sgIsBigEndian() ) {            
+            sgEndianSwap((uint64_t *) p + 0);
+            sgEndianSwap((uint64_t *) p + 1);
+            sgEndianSwap((uint64_t *) p + 2);
+        }
+        
+        offset += 3 * sizeof(double);
+        return SGVec3d(p);
+    }
+    
+    float readFloat()
+    {
+        float* p = reinterpret_cast<float*>(ptr + offset);
+        if ( sgIsBigEndian() ) {            
+            sgEndianSwap((uint32_t *) p);
+        }
+        
+        offset += sizeof(float);
+        return *p;
+    }
+    
+    SGVec2f readVec2f()
+    {
+        float* p = reinterpret_cast<float*>(ptr + offset);
+        
+        if ( sgIsBigEndian() ) {            
+            sgEndianSwap((uint32_t *) p + 0);
+            sgEndianSwap((uint32_t *) p + 1);
+        }
+        
+        offset += 2 * sizeof(float);
+        return SGVec2f(p);
+    }
+    
+    SGVec3f readVec3f()
+    {
+        float* p = reinterpret_cast<float*>(ptr + offset);
+        
+        if ( sgIsBigEndian() ) {            
+            sgEndianSwap((uint32_t *) p + 0);
+            sgEndianSwap((uint32_t *) p + 1);
+            sgEndianSwap((uint32_t *) p + 2);
+        }
+        
+        offset += 3 * sizeof(float);
+        return SGVec3f(p);
+    }
+    
+    SGVec4f readVec4f()
+    {
+        float* p = reinterpret_cast<float*>(ptr + offset);
+        
+        if ( sgIsBigEndian() ) {            
+            sgEndianSwap((uint32_t *) p + 0);
+            sgEndianSwap((uint32_t *) p + 1);
+            sgEndianSwap((uint32_t *) p + 2);
+            sgEndianSwap((uint32_t *) p + 3);
+        }
+        
+        offset += 4 * sizeof(float);
+        return SGVec4f(p);
     }
 };
 
+template <class T>
+static void read_indices(char* buffer, 
+                         size_t bytes,
+                         int indexMask,
+                         int_list& vertices, 
+                         int_list& normals,
+                         int_list& colors,
+                         int_list& texCoords)
+{
+    const int indexSize = sizeof(T) * std::bitset<32>(indexMask).count();
+    const int count = bytes / indexSize;
+    
+// fix endian-ness of the whole lot, if required
+    if (sgIsBigEndian()) {
+        int indices = bytes / sizeof(T);
+        T* src = reinterpret_cast<T*>(buffer);
+        for (int i=0; i<indices; ++i) {
+            sgEndianSwap(src++);
+        }
+    }
+    
+    T* src = reinterpret_cast<T*>(buffer);
+    for (int i=0; i<count; ++i) {
+        if (indexMask & SG_IDX_VERTICES) vertices.push_back(*src++);
+        if (indexMask & SG_IDX_NORMALS) normals.push_back(*src++);
+        if (indexMask & SG_IDX_COLORS) colors.push_back(*src++);
+        if (indexMask & SG_IDX_TEXCOORDS) texCoords.push_back(*src++);
+    } // of elements in the index
+}
+
+template <class T>
+void write_indice(gzFile fp, T value)
+{
+    sgWriteBytes(fp, sizeof(T), &value);
+}
+
+// specialize template to call endian-aware conversion methods
+template <>
+void write_indice(gzFile fp, uint16_t value)
+{
+    sgWriteUShort(fp, value);
+}
+
+template <>
+void write_indice(gzFile fp, uint32_t value)
+{
+    sgWriteUInt(fp, value);
+}
+
+
+template <class T>
+void write_indices(gzFile fp, unsigned char indexMask, 
+    const int_list& vertices, 
+    const int_list& normals, 
+    const int_list& colors,
+    const int_list& texCoords)
+{
+    unsigned int count = vertices.size();
+    const int indexSize = sizeof(T) * std::bitset<32>(indexMask).count();
+    sgWriteUInt(fp, indexSize * count);
+            
+    for (unsigned int i=0; i < count; ++i) {
+        write_indice(fp, static_cast<T>(vertices[i]));
+        
+        if (indexMask & SG_IDX_NORMALS) {
+            write_indice(fp, static_cast<T>(normals[i]));
+        }
+        if (indexMask & SG_IDX_COLORS) {
+            write_indice(fp, static_cast<T>(colors[i]));
+        }
+        if (indexMask & SG_IDX_TEXCOORDS) {
+            write_indice(fp, static_cast<T>(texCoords[i]));
+        }
+    }
+}
+
+
 // read object properties
-static void read_object( gzFile fp,
-			 int obj_type,
-			 int nproperties,
-			 int nelements,
-			 group_list *vertices,
-			 group_list *normals,
-			 group_list *colors,
-			 group_list *texcoords,
-			 string_list *materials )
+void SGBinObject::read_object( gzFile fp,
+                         int obj_type,
+                         int nproperties,
+                         int nelements,
+                         group_list& vertices, 
+                          group_list& normals,
+                          group_list& colors,
+                          group_list& texCoords,
+                          string_list& materials)
 {
     unsigned int nbytes;
     unsigned char idx_mask;
-    int idx_size;
-    bool do_vertices, do_normals, do_colors, do_texcoords;
-    int j, k, idx;
+    int j;
     sgSimpleBuffer buf( 32768 );  // 32 Kb
     char material[256];
 
     // default values
     if ( obj_type == SG_POINTS ) {
-	idx_size = 1;
-	idx_mask = SG_IDX_VERTICES;
-	do_vertices = true;
-	do_normals = false;
-	do_colors = false;
-	do_texcoords = false;
+        idx_mask = SG_IDX_VERTICES;
     } else {
-	idx_size = 2;
-	idx_mask = (char)(SG_IDX_VERTICES | SG_IDX_TEXCOORDS);
-	do_vertices = true;
-	do_normals = false;
-	do_colors = false;
-	do_texcoords = true;
+        idx_mask = (char)(SG_IDX_VERTICES | SG_IDX_TEXCOORDS);
     }
 
     for ( j = 0; j < nproperties; ++j ) {
-	char prop_type;
-	sgReadChar( fp, &prop_type );
-
-	sgReadUInt( fp, &nbytes );
-	// cout << "property size = " << nbytes << endl;
-	if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-	char *ptr = buf.get_ptr();
-	sgReadBytes( fp, nbytes, ptr );
-	if ( prop_type == SG_MATERIAL ) {
-	    strncpy( material, ptr, nbytes );
-	    material[nbytes] = '\0';
-	    // cout << "material type = " << material << endl;
-	} else if ( prop_type == SG_INDEX_TYPES ) {
-	    idx_mask = ptr[0];
-	    // cout << "idx_mask = " << (int)idx_mask << endl;
-	    idx_size = 0;
-	    do_vertices = false;
-	    do_normals = false;
-	    do_colors = false;
-	    do_texcoords = false;
-	    if ( idx_mask & SG_IDX_VERTICES ) {
-		do_vertices = true;
-		++idx_size;
-	    }
-	    if ( idx_mask & SG_IDX_NORMALS ) {
-		do_normals = true;
-		++idx_size;
-	    }
-	    if ( idx_mask & SG_IDX_COLORS ) {
-		do_colors = true;
-		++idx_size;
-	    }
-	    if ( idx_mask & SG_IDX_TEXCOORDS ) {
-		do_texcoords = true;
-		++idx_size;
-	    }
-	}
-    }
-
+        char prop_type;
+        sgReadChar( fp, &prop_type );
+        sgReadUInt( fp, &nbytes );
+        buf.resize(nbytes);
+        char *ptr = buf.get_ptr();
+        sgReadBytes( fp, nbytes, ptr );
+        if ( prop_type == SG_MATERIAL ) {
+            if (nbytes > 255) {
+                nbytes = 255;
+            }
+            strncpy( material, ptr, nbytes );
+            material[nbytes] = '\0';
+            // cout << "material type = " << material << endl;
+        } else if ( prop_type == SG_INDEX_TYPES ) {
+            idx_mask = ptr[0];
+            //cout << std::hex << "index mask:" << idx_mask << std::dec << endl;
+        }
+    }
+
+    if ( sgReadError() ) {
+        cout << "We detected an error reading object properties"  << endl;
+        return;
+    }
+    
     for ( j = 0; j < nelements; ++j ) {
-	sgReadUInt( fp, &nbytes );
-	// cout << "element size = " << nbytes << endl;
-	if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-	char *ptr = buf.get_ptr();
-	sgReadBytes( fp, nbytes, ptr );
-	int count = nbytes / (idx_size * sizeof(unsigned short));
-	unsigned short *sptr = (unsigned short *)ptr;
-	int_list vs; vs.clear();
-	int_list ns; ns.clear();
-	int_list cs; cs.clear();
-	int_list tcs; tcs.clear();
-	for ( k = 0; k < count; ++k ) {
-	    if ( sgIsBigEndian() ) {
-		for ( idx = 0; idx < idx_size; ++idx ) {
-		    sgEndianSwap( (uint16_t *)&(sptr[idx]) );
-		}
-	    }
-	    idx = 0;
-	    if ( do_vertices ) {
-		vs.push_back( sptr[idx++] );
-	    }
-	    if ( do_normals ) {
-		ns.push_back( sptr[idx++] );
-		    }
-	    if ( do_colors ) {
-		cs.push_back( sptr[idx++] );
-	    }
-	    if ( do_texcoords ) {
-		tcs.push_back( sptr[idx++] );
-	    }
-	    // cout << sptr[0] << " ";
-	    sptr += idx_size;
-	}
-	// cout << endl;
-	vertices->push_back( vs );
-	normals->push_back( ns );
-	colors->push_back( cs );
-	texcoords->push_back( tcs );
-	materials->push_back( material );
-    }
+        sgReadUInt( fp, &nbytes );
+        if ( sgReadError() ) {
+            cout << "We detected an error reading element size for :" << j << endl;
+            return;
+        }
+        
+        buf.resize( nbytes );
+        char *ptr = buf.get_ptr();
+        sgReadBytes( fp, nbytes, ptr );
+        
+        if ( sgReadError() ) {
+            cout << "We detected an error reading object element:" << j << "bytes="<< nbytes  << endl;
+            return;
+        }
+                
+        int_list vs;
+        int_list ns;
+        int_list cs;
+        int_list tcs;
+        if (version >= 10) {
+            read_indices<uint32_t>(ptr, nbytes, idx_mask, vs, ns, cs, tcs);
+        } else {
+            read_indices<uint16_t>(ptr, nbytes, idx_mask, vs, ns, cs, tcs);
+        }
+
+        vertices.push_back( vs );
+        normals.push_back( ns );
+        colors.push_back( cs );
+        texCoords.push_back( tcs );
+        materials.push_back( material );
+    } // of element iteration
 }
 
 
 // read a binary file and populate the provided structures.
 bool SGBinObject::read_bin( const string& file ) {
     SGVec3d p;
-    int i, j, k;
+    int i, k;
+    size_t j;
     unsigned int nbytes;
     sgSimpleBuffer buf( 32768 );  // 32 Kb
 
@@ -279,13 +400,13 @@
 
     gzFile fp;
     if ( (fp = gzopen( file.c_str(), "rb" )) == NULL ) {
-	string filegz = file + ".gz";
-	if ( (fp = gzopen( filegz.c_str(), "rb" )) == NULL ) {
+        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!");
 
-	    return false;
-	}
+            return false;
+        }
     }
 
     sgClearReadError();
@@ -294,16 +415,16 @@
     unsigned int header;
     sgReadUInt( fp, &header );
     if ( ((header & 0xFF000000) >> 24) == 'S' &&
-	 ((header & 0x00FF0000) >> 16) == 'G' ) {
-	// cout << "Good header" << endl;
-	// read file version
-	version = (header & 0x0000FFFF);
-	// cout << "File version = " << version << endl;
+         ((header & 0x00FF0000) >> 16) == 'G' ) {
+        // cout << "Good header" << endl;
+        // read file version
+        version = (header & 0x0000FFFF);
+        // cout << "File version = " << version << endl;
     } else {
-	// close the file before we return
-	gzclose(fp);
-
-	return false;
+        // close the file before we return
+        gzclose(fp);
+
+        return false;
     }
 
     // read creation time
@@ -324,673 +445,392 @@
 #endif
 
     // read number of top level objects
-    unsigned short nobjects;
-    if ( version >= 7 ) {
-        sgReadUShort( fp, &nobjects );
+    int nobjects;
+    if ( version >= 10) { // version 10 extends everything to be 32-bit
+        sgReadInt( fp, &nobjects );
+    } else if ( version >= 7 ) {
+        uint16_t v;
+        sgReadUShort( fp, &v );
+        nobjects = v;
     } else {
-        short tmp;
-        sgReadShort( fp, &tmp );
-        nobjects = tmp;
-    }
-    // cout << "Total objects to read = " << nobjects << endl;
-
+        int16_t v;
+        sgReadShort( fp, &v );
+        nobjects = v;
+    }
+     
+     //cout << "Total objects to read = " << nobjects << endl;
+
+    if ( sgReadError() ) {
+        cout << "Error while reading header of file " << file << "(.gz)" << endl;
+        return false;
+    }
+    
     // read in objects
     for ( i = 0; i < nobjects; ++i ) {
-	// read object header
-	char obj_type;
-	unsigned short nproperties, nelements;
-	sgReadChar( fp, &obj_type );
-        if ( version >= 7 ) {
-            sgReadUShort( fp, &nproperties );
-            sgReadUShort( fp, &nelements );
+        // read object header
+        char obj_type;
+        uint32_t nproperties, nelements;
+        sgReadChar( fp, &obj_type );
+        if ( version >= 10 ) {
+            sgReadUInt( fp, &nproperties );
+            sgReadUInt( fp, &nelements );
+        } else if ( version >= 7 ) {
+            uint16_t v;
+            sgReadUShort( fp, &v );
+            nproperties = v;
+            sgReadUShort( fp, &v );
+            nelements = v;
         } else {
-            short tmp;
-            sgReadShort( fp, &tmp );
-            nproperties = tmp;
-            sgReadShort( fp, &tmp );
-            nelements = tmp;
-        }
-
-	// cout << "object " << i << " = " << (int)obj_type << " props = "
-	//      << nproperties << " elements = " << nelements << endl;
-	    
-	if ( obj_type == SG_BOUNDING_SPHERE ) {
-	    // read bounding sphere properties
-	    for ( j = 0; j < nproperties; ++j ) {
-		char prop_type;
-		sgReadChar( fp, &prop_type );
-
-		sgReadUInt( fp, &nbytes );
-		// cout << "property size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-	    }
-
-	    // read bounding sphere elements
-	    for ( j = 0; j < nelements; ++j ) {
-		sgReadUInt( fp, &nbytes );
-		// cout << "element size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-
-		double *dptr = (double *)ptr;
-		if ( sgIsBigEndian() ) {
-		    sgEndianSwap( (uint64_t *)&(dptr[0]) );
-		    sgEndianSwap( (uint64_t *)&(dptr[1]) );
-		    sgEndianSwap( (uint64_t *)&(dptr[2]) );
-		}
-		gbs_center = SGVec3d( dptr[0], dptr[1], dptr[2] );
-		// cout << "Center = " << gbs_center << endl;
-		ptr += sizeof(double) * 3;
-		
-		float *fptr = (float *)ptr;
-		if ( sgIsBigEndian() ) {
-		    sgEndianSwap( (uint32_t *)fptr );
-		}
-		gbs_radius = fptr[0];
-		// cout << "Bounding radius = " << gbs_radius << endl;
-	    }
-	} else if ( obj_type == SG_VERTEX_LIST ) {
-	    // read vertex list properties
-	    for ( j = 0; j < nproperties; ++j ) {
-		char prop_type;
-		sgReadChar( fp, &prop_type );
-
-		sgReadUInt( fp, &nbytes );
-		// cout << "property size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-	    }
-
-	    // read vertex list elements
-	    for ( j = 0; j < nelements; ++j ) {
-		sgReadUInt( fp, &nbytes );
-		// cout << "element size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-		int count = nbytes / (sizeof(float) * 3);
-		float *fptr = (float *)ptr;
-		wgs84_nodes.reserve( count );
-		for ( k = 0; k < count; ++k ) {
-		    if ( sgIsBigEndian() ) {
-			sgEndianSwap( (uint32_t *)&(fptr[0]) );
-			sgEndianSwap( (uint32_t *)&(fptr[1]) );
-			sgEndianSwap( (uint32_t *)&(fptr[2]) );
-		    }
-		    wgs84_nodes.push_back( SGVec3d(fptr[0], fptr[1], fptr[2]) );
-		    fptr += 3;
-		}
-	    }
-	} else if ( obj_type == SG_COLOR_LIST ) {
-	    // read color list properties
-	    for ( j = 0; j < nproperties; ++j ) {
-		char prop_type;
-		sgReadChar( fp, &prop_type );
-
-		sgReadUInt( fp, &nbytes );
-		// cout << "property size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-	    }
-
-	    // read color list elements
-	    for ( j = 0; j < nelements; ++j ) {
-		sgReadUInt( fp, &nbytes );
-		// cout << "element size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-		int count = nbytes / (sizeof(float) * 4);
-		float *fptr = (float *)ptr;
-		colors.reserve(count);
-		for ( k = 0; k < count; ++k ) {
-		    if ( sgIsBigEndian() ) {
-			sgEndianSwap( (uint32_t *)&(fptr[0]) );
-			sgEndianSwap( (uint32_t *)&(fptr[1]) );
-			sgEndianSwap( (uint32_t *)&(fptr[2]) );
-			sgEndianSwap( (uint32_t *)&(fptr[3]) );
-		    }
-		    SGVec4f color( fptr[0], fptr[1], fptr[2], fptr[3] );
-		    colors.push_back( color );
-		    fptr += 4;
-		}
-	    }
-	} else if ( obj_type == SG_NORMAL_LIST ) {
-	    // read normal list properties
-	    for ( j = 0; j < nproperties; ++j ) {
-		char prop_type;
-		sgReadChar( fp, &prop_type );
-
-		sgReadUInt( fp, &nbytes );
-		// cout << "property size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-	    }
-
-	    // read normal list elements
-	    for ( j = 0; j < nelements; ++j ) {
-		sgReadUInt( fp, &nbytes );
-		// cout << "element size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		unsigned char *ptr = (unsigned char *)(buf.get_ptr());
-		sgReadBytes( fp, nbytes, ptr );
-		int count = nbytes / 3;
-		normals.reserve( count );
-		for ( k = 0; k < count; ++k ) {
-                    SGVec3f normal((ptr[0]) / 127.5 - 1.0,
-                                   (ptr[1]) / 127.5 - 1.0,
-                                   (ptr[2]) / 127.5 - 1.0);
-
-		    normals.push_back(normalize(normal));
-		    ptr += 3;
-		}
-	    }
-	} else if ( obj_type == SG_TEXCOORD_LIST ) {
-	    // read texcoord list properties
-	    for ( j = 0; j < nproperties; ++j ) {
-		char prop_type;
-		sgReadChar( fp, &prop_type );
-
-		sgReadUInt( fp, &nbytes );
-		// cout << "property size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-	    }
-
-	    // read texcoord list elements
-	    for ( j = 0; j < nelements; ++j ) {
-		sgReadUInt( fp, &nbytes );
-		// cout << "element size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-		int count = nbytes / (sizeof(float) * 2);
-		float *fptr = (float *)ptr;
-		texcoords.reserve(count);
-		for ( k = 0; k < count; ++k ) {
-		    if ( sgIsBigEndian() ) {
-			sgEndianSwap( (uint32_t *)&(fptr[0]) );
-			sgEndianSwap( (uint32_t *)&(fptr[1]) );
-		    }
-		    texcoords.push_back( SGVec2f( fptr[0], fptr[1] ) );
-		    fptr += 2;
-		}
-	    }
-	} else if ( obj_type == SG_POINTS ) {
-	    // read point elements
-	    read_object( fp, SG_POINTS, nproperties, nelements,
-			 &pts_v, &pts_n, &pts_c, &pts_tc, &pt_materials );
-	} else if ( obj_type == SG_TRIANGLE_FACES ) {
-	    // read triangle face properties
-	    read_object( fp, SG_TRIANGLE_FACES, nproperties, nelements,
-			 &tris_v, &tris_n, &tris_c, &tris_tc, &tri_materials );
-	} else if ( obj_type == SG_TRIANGLE_STRIPS ) {
-	    // read triangle strip properties
-	    read_object( fp, SG_TRIANGLE_STRIPS, nproperties, nelements,
-			 &strips_v, &strips_n, &strips_c, &strips_tc,
-			 &strip_materials );
-	} else if ( obj_type == SG_TRIANGLE_FANS ) {
-	    // read triangle fan properties
-	    read_object( fp, SG_TRIANGLE_FANS, nproperties, nelements,
-			 &fans_v, &fans_n, &fans_c, &fans_tc, &fan_materials );
-	} else {
-	    // unknown object type, just skip
-
-	    // read properties
-	    for ( j = 0; j < nproperties; ++j ) {
-		char prop_type;
-		sgReadChar( fp, &prop_type );
-
-		sgReadUInt( fp, &nbytes );
-		// cout << "property size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-	    }
-
-	    // read elements
-	    for ( j = 0; j < nelements; ++j ) {
-		sgReadUInt( fp, &nbytes );
-		// cout << "element size = " << nbytes << endl;
-		if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
-		char *ptr = buf.get_ptr();
-		sgReadBytes( fp, nbytes, ptr );
-	    }
-	}
+            int16_t v;
+            sgReadShort( fp, &v );
+            nproperties = v;
+            sgReadShort( fp, &v );
+            nelements = v;
+        }
+
+         //cout << "object " << i << " = " << (int)obj_type << " props = "
+         //     << nproperties << " elements = " << nelements << endl;
+            
+        if ( obj_type == SG_BOUNDING_SPHERE ) {
+            // read bounding sphere properties
+            read_properties( fp, nproperties );
+            
+            // read bounding sphere elements
+            for ( j = 0; j < nelements; ++j ) {
+                sgReadUInt( fp, &nbytes );
+                buf.resize( nbytes );
+                buf.reset();
+                char *ptr = buf.get_ptr();
+                sgReadBytes( fp, nbytes, ptr );
+                gbs_center = buf.readVec3d();
+                gbs_radius = buf.readFloat();
+            }
+        } else if ( obj_type == SG_VERTEX_LIST ) {
+            // read vertex list properties
+            read_properties( fp, nproperties );
+
+            // read vertex list elements
+            for ( j = 0; j < nelements; ++j ) {
+                sgReadUInt( fp, &nbytes );
+                buf.resize( nbytes );
+                buf.reset();
+                char *ptr = buf.get_ptr();
+                sgReadBytes( fp, nbytes, ptr );
+                int count = nbytes / (sizeof(float) * 3);
+                wgs84_nodes.reserve( count );
+                for ( k = 0; k < count; ++k ) {
+                    SGVec3f v = buf.readVec3f();
+                // extend from float to double, hmmm
+                    wgs84_nodes.push_back( SGVec3d(v[0], v[1], v[2]) );
+                }
+            }
+        } else if ( obj_type == SG_COLOR_LIST ) {
+            // read color list properties
+            read_properties( fp, nproperties );
+
+            // read color list elements
+            for ( j = 0; j < nelements; ++j ) {
+                sgReadUInt( fp, &nbytes );
+                buf.resize( nbytes );
+                buf.reset();
+                char *ptr = buf.get_ptr();
+                sgReadBytes( fp, nbytes, ptr );
+                int count = nbytes / (sizeof(float) * 4);
+                colors.reserve(count);
+                for ( k = 0; k < count; ++k ) {
+                    colors.push_back( buf.readVec4f() );
+                }
+            }
+        } else if ( obj_type == SG_NORMAL_LIST ) {
+            // read normal list properties
+            read_properties( fp, nproperties );
+
+            // read normal list elements
+            for ( j = 0; j < nelements; ++j ) {
+                sgReadUInt( fp, &nbytes );
+                buf.resize( nbytes );
+                buf.reset();
+                unsigned char *ptr = (unsigned char *)(buf.get_ptr());
+                sgReadBytes( fp, nbytes, ptr );
+                int count = nbytes / 3;
+                normals.reserve( count );
+ 
+                for ( k = 0; k < count; ++k ) {
+                    SGVec3f normal( (ptr[0]) / 127.5 - 1.0,
+                                    (ptr[1]) / 127.5 - 1.0, 
+                                    (ptr[2]) / 127.5 - 1.0);
+                    normals.push_back(normalize(normal));
+                    ptr += 3;
+                }
+            }
+        } else if ( obj_type == SG_TEXCOORD_LIST ) {
+            // read texcoord list properties
+            read_properties( fp, nproperties );
+
+            // read texcoord list elements
+            for ( j = 0; j < nelements; ++j ) {
+                sgReadUInt( fp, &nbytes );
+                buf.resize( nbytes );
+                buf.reset();
+                char *ptr = buf.get_ptr();
+                sgReadBytes( fp, nbytes, ptr );
+                int count = nbytes / (sizeof(float) * 2);
+                texcoords.reserve(count);
+                for ( k = 0; k < count; ++k ) {
+                    texcoords.push_back( buf.readVec2f() );
+                }
+            }
+        } else if ( obj_type == SG_POINTS ) {
+            // read point elements
+            read_object( fp, SG_POINTS, nproperties, nelements,
+                         pts_v, pts_n, pts_c, pts_tc, pt_materials );
+        } else if ( obj_type == SG_TRIANGLE_FACES ) {
+            // read triangle face properties
+            read_object( fp, SG_TRIANGLE_FACES, nproperties, nelements,
+                         tris_v, tris_n, tris_c, tris_tc, tri_materials );
+        } else if ( obj_type == SG_TRIANGLE_STRIPS ) {
+            // read triangle strip properties
+            read_object( fp, SG_TRIANGLE_STRIPS, nproperties, nelements,
+                         strips_v, strips_n, strips_c, strips_tc,
+                         strip_materials );
+        } else if ( obj_type == SG_TRIANGLE_FANS ) {
+            // read triangle fan properties
+            read_object( fp, SG_TRIANGLE_FANS, nproperties, nelements,
+                         fans_v, fans_n, fans_c, fans_tc, fan_materials );
+        } else {
+            // unknown object type, just skip
+            read_properties( fp, nproperties );
+
+            // read elements
+            for ( j = 0; j < nelements; ++j ) {
+                sgReadUInt( fp, &nbytes );
+                // cout << "element size = " << nbytes << endl;
+                if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
+                char *ptr = buf.get_ptr();
+                sgReadBytes( fp, nbytes, ptr );
+            }
+        }
+        
+        if ( sgReadError() ) {
+            cout << "Error while reading object:" << i << " in file " << file << "(.gz)" << endl;
+            return false;
+        }
     }
 
     // close the file
     gzclose(fp);
 
     if ( sgReadError() ) {
-	cout << "We detected an error while reading the file." << endl;
-	return false;
+        cout << "Error while reading file " << file << "(.gz)" << endl;
+        return false;
     }
 
     return true;
 }
 
+void SGBinObject::write_header(gzFile fp, int type, int nProps, int nElements)
+{
+    sgWriteChar(fp, (unsigned char) type);
+    if (version == 7) {
+        sgWriteUShort(fp, nProps);
+        sgWriteUShort(fp, nElements);
+    } else {
+        sgWriteUInt(fp, nProps);
+        sgWriteUInt(fp, nElements);
+    }
+}
+
+unsigned int SGBinObject::count_objects(const string_list& materials)
+{
+    unsigned int result = 0;
+    unsigned int start = 0, end = 1;
+    unsigned int count = materials.size();
+    string m;
+    
+    while ( start < count ) {
+        m = materials[start];
+        for (end = start+1; (end < count) && (m == materials[end]); ++end) { }     
+        ++result;
+        start = end; 
+    }
+    
+    return result;
+}
+
+void SGBinObject::write_objects(gzFile fp, int type, const group_list& verts,
+    const group_list& normals, const group_list& colors, 
+    const group_list& texCoords, const string_list& materials)
+{
+    if (verts.empty()) {
+        return;
+    }
+    
+    unsigned int start = 0, end = 1;
+    string m;
+    int_list emptyList;
+    
+    while (start < materials.size()) {
+        m = materials[start];
+    // find range of objects with identical material, write out as a single object
+        for (end = start+1; (end < materials.size()) && (m == materials[end]); ++end) {}
+    
+        const int count = end - start;
+        write_header(fp, type, 2, count);
+        
+    // properties
+        sgWriteChar( fp, (char)SG_MATERIAL );        // property
+        sgWriteUInt( fp, m.length() );        // nbytes
+        sgWriteBytes( fp, m.length(), m.c_str() );
+    
+        unsigned char idx_mask = 0;
+        if ( !verts.empty() && !verts.front().empty()) idx_mask |= SG_IDX_VERTICES;
+        if ( !normals.empty() && !normals.front().empty()) idx_mask |= SG_IDX_NORMALS;
+        if ( !colors.empty() && !colors.front().empty()) idx_mask |= SG_IDX_COLORS;
+        if ( !texCoords.empty() && !texCoords.front().empty()) idx_mask |= SG_IDX_TEXCOORDS;
+        sgWriteChar( fp, (char)SG_INDEX_TYPES );     // property
+        sgWriteUInt( fp, 1 );                        // nbytes
+        sgWriteChar( fp, idx_mask );
+    
+//        cout << "material:" << m << ", count =" << count << endl;
+    // elements
+        for (unsigned int i=start; i < end; ++i) {
+            const int_list& va(verts[i]);
+            const int_list& na((idx_mask & SG_IDX_NORMALS) ? normals[i] : emptyList);
+            const int_list& ca((idx_mask & SG_IDX_COLORS) ? colors[i] : emptyList);
+            const int_list& tca((idx_mask & SG_IDX_TEXCOORDS) ? texCoords[i] : emptyList);
+            
+            if (version == 7) {
+                write_indices<uint16_t>(fp, idx_mask, va, na, ca, tca);
+            } else {
+                write_indices<uint32_t>(fp, idx_mask, va, na, ca, tca);
+            }
+        }
+    
+        start = end;
+    } // of materials iteration
+}
 
 // write out the structures to a binary file.  We assume that the
 // groups come to us sorted by material property.  If not, things
 // don't break, but the result won't be as optimal.
 bool SGBinObject::write_bin( const string& base, const string& name,
-			     const SGBucket& b )
-{
-    int i, j;
-    unsigned char idx_mask;
-    int idx_size;
+                             const SGBucket& b )
+{
 
     SGPath file = base + "/" + b.gen_base_path() + "/" + name + ".gz";
-    file.create_dir( 0755 );
+    return write_bin_file(file);
+}
+
+bool SGBinObject::write_bin_file(const SGPath& file)
+{
+    int i;
+    
+    SGPath file2(file);
+    file2.create_dir( 0755 );
     cout << "Output file = " << file.str() << endl;
 
     gzFile fp;
     if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
-	cout << "ERROR: opening " << file.str() << " for writing!" << endl;
-	return false;
+        cout << "ERROR: opening " << file.str() << " for writing!" << endl;
+        return false;
     }
 
     sgClearWriteError();
 
     cout << "points size = " << pts_v.size() << "  pt_materials = " 
-	 << pt_materials.size() << endl;
+         << pt_materials.size() << endl;
     cout << "triangles size = " << tris_v.size() << "  tri_materials = " 
-	 << tri_materials.size() << endl;
+         << tri_materials.size() << endl;
     cout << "strips size = " << strips_v.size() << "  strip_materials = " 
-	 << strip_materials.size() << endl;
+         << strip_materials.size() << endl;
     cout << "fans size = " << fans_v.size() << "  fan_materials = " 
-	 << fan_materials.size() << endl;
+         << fan_materials.size() << endl;
 
     cout << "nodes = " << wgs84_nodes.size() << endl;
     cout << "colors = " << colors.size() << endl;
     cout << "normals = " << normals.size() << endl;
     cout << "tex coords = " << texcoords.size() << endl;
 
+    version = 10;
+    if ((wgs84_nodes.size() < 0xffff) &&
+        (normals.size() < 0xffff) &&
+        (texcoords.size() < 0xffff)) {
+        version = 7; // use smaller indices if possible
+    }
+
     // write header magic
+    
+    /** Magic Number for our file format */
+    #define SG_FILE_MAGIC_NUMBER  ( ('S'<<24) + ('G'<<16) + version )
+    
     sgWriteUInt( fp, SG_FILE_MAGIC_NUMBER );
     time_t calendar_time = time(NULL);
     sgWriteLong( fp, (int32_t)calendar_time );
 
     // calculate and write number of top level objects
-    string material;
-    int start;
-    int end;
-    unsigned short nobjects = 0;
-    nobjects++;			// for gbs
-    nobjects++;			// for vertices
-    nobjects++;			// for colors
-    nobjects++;			// for normals
-    nobjects++;			// for texcoords
-
-    // points
-    unsigned short npts = 0;
-    start = 0; end = 1;
-    while ( start < (int)pt_materials.size() ) {
-	material = pt_materials[start];
-	while ( (end < (int)pt_materials.size()) &&
-		(material == pt_materials[end]) ) {
-	    end++;
-	}
-	npts++;
-	start = end; end = start + 1;
-    }
-    nobjects += npts;
-
-    // tris
-    unsigned short ntris = 0;
-    start = 0; end = 1;
-    while ( start < (int)tri_materials.size() ) {
-	material = tri_materials[start];
-	while ( (end < (int)tri_materials.size()) &&
-		(material == tri_materials[end]) ) {
-	    end++;
-	}
-	ntris++;
-	start = end; end = start + 1;
-    }
-    nobjects += ntris;
-
-    // strips
-    unsigned short nstrips = 0;
-    start = 0; end = 1;
-    while ( start < (int)strip_materials.size() ) {
-	material = strip_materials[start];
-	while ( (end < (int)strip_materials.size()) &&
-		(material == strip_materials[end]) ) {
-	    end++;
-	}
-	nstrips++;
-	start = end; end = start + 1;
-    }
-    nobjects += nstrips;
-
-    // fans
-    unsigned short nfans = 0;
-    start = 0; end = 1;
-    while ( start < (int)fan_materials.size() ) {
-	material = fan_materials[start];
-	while ( (end < (int)fan_materials.size()) &&
-		(material == fan_materials[end]) ) {
-	    end++;
-	}
-	nfans++;
-	start = end; end = start + 1;
-    }
-    nobjects += nfans;
+    int nobjects = 5; // gbs, vertices, colors, normals, texcoords
+    nobjects += count_objects(pt_materials);
+    nobjects += count_objects(tri_materials);
+    nobjects += count_objects(strip_materials);
+    nobjects += count_objects(fan_materials);
 
     cout << "total top level objects = " << nobjects << endl;
-    sgWriteUShort( fp, nobjects );
-
+    if (version == 7) {
+        sgWriteUShort( fp, (uint16_t) nobjects );
+    } else {
+        sgWriteInt( fp, nobjects );
+    } 
+    
     // write bounding sphere
-    sgWriteChar( fp, (char)SG_BOUNDING_SPHERE );        // type
-    sgWriteUShort( fp, 0 );		                // nproperties
-    sgWriteUShort( fp, 1 );		                // nelements
-
+    write_header( fp, SG_BOUNDING_SPHERE, 0, 1);
     sgWriteUInt( fp, sizeof(double) * 3 + sizeof(float) ); // nbytes
     sgWritedVec3( fp, gbs_center );
     sgWriteFloat( fp, gbs_radius );
 
     // dump vertex list
-    sgWriteChar( fp, (char)SG_VERTEX_LIST );             // type
-    sgWriteUShort( fp, 0 );		                 // nproperties
-    sgWriteUShort( fp, 1 );		                 // nelements
+    write_header( fp, SG_VERTEX_LIST, 0, 1);
     sgWriteUInt( fp, wgs84_nodes.size() * sizeof(float) * 3 ); // nbytes
     for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
         sgWriteVec3( fp, toVec3f(wgs84_nodes[i] - gbs_center));
     }
 
     // dump vertex color list
-    sgWriteChar( fp, (char)SG_COLOR_LIST );             // type
-    sgWriteUShort( fp, 0 );		                 // nproperties
-    sgWriteUShort( fp, 1 );		                 // nelements
+    write_header( fp, SG_COLOR_LIST, 0, 1);
     sgWriteUInt( fp, colors.size() * sizeof(float) * 4 ); // nbytes
     for ( i = 0; i < (int)colors.size(); ++i ) {
       sgWriteVec4( fp, colors[i]);
     }
 
     // dump vertex normal list
-    sgWriteChar( fp, (char)SG_NORMAL_LIST );            // type
-    sgWriteUShort( fp, 0 );		                // nproperties
-    sgWriteUShort( fp, 1 );		                // nelements
+    write_header( fp, SG_NORMAL_LIST, 0, 1);
     sgWriteUInt( fp, normals.size() * 3 );              // nbytes
     char normal[3];
     for ( i = 0; i < (int)normals.size(); ++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);
-	sgWriteBytes( fp, 3, normal );
+        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);
+        sgWriteBytes( fp, 3, normal );
     }
 
     // dump texture coordinates
-    sgWriteChar( fp, (char)SG_TEXCOORD_LIST );          // type
-    sgWriteUShort( fp, 0 );		                // nproperties
-    sgWriteUShort( fp, 1 );		                // nelements
+    write_header( fp, SG_TEXCOORD_LIST, 0, 1);
     sgWriteUInt( fp, texcoords.size() * sizeof(float) * 2 ); // nbytes
     for ( i = 0; i < (int)texcoords.size(); ++i ) {
       sgWriteVec2( fp, texcoords[i]);
     }
 
-    // dump point groups if they exist
-    if ( pts_v.size() > 0 ) {
-	int start = 0;
-	int end = 1;
-	string material;
-	while ( start < (int)pt_materials.size() ) {
-	    // find next group
-	    material = pt_materials[start];
-	    while ( (end < (int)pt_materials.size()) && 
-		    (material == pt_materials[end]) )
-		{
-		    // cout << "end = " << end << endl;
-		    end++;
-		}
-	    // cout << "group = " << start << " to " << end - 1 << endl;
-
-	    // write group headers
-	    sgWriteChar( fp, (char)SG_POINTS );          // type
-	    sgWriteUShort( fp, 2 );		         // nproperties
-	    sgWriteUShort( fp, end - start );             // nelements
-
-	    sgWriteChar( fp, (char)SG_MATERIAL );        // property
-	    sgWriteUInt( fp, material.length() );        // nbytes
-	    sgWriteBytes( fp, material.length(), material.c_str() );
-
-	    idx_mask = 0;
-	    idx_size = 0;
-	    if ( pts_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; }
-	    if ( pts_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; }
-	    if ( pts_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; }
-	    if ( pts_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size; }
-	    sgWriteChar( fp, (char)SG_INDEX_TYPES );     // property
-	    sgWriteUInt( fp, 1 );                        // nbytes
-	    sgWriteChar( fp, idx_mask );
-
-	    // write strips
-	    for ( i = start; i < end; ++i ) {
-		// nbytes
-		sgWriteUInt( fp, pts_v[i].size() * idx_size
-                                 * sizeof(unsigned short) );
-		for ( j = 0; j < (int)pts_v[i].size(); ++j ) {
-		    if ( pts_v.size() ) { 
-			sgWriteUShort( fp, (unsigned short)pts_v[i][j] );
-		    }
-		    if ( pts_n.size() ) { 
-			sgWriteUShort( fp, (unsigned short)pts_n[i][j] );
-		    }
-		    if ( pts_c.size() ) { 
-			sgWriteUShort( fp, (unsigned short)pts_c[i][j] );
-		    }
-		    if ( pts_tc.size() ) { 
-			sgWriteUShort( fp, (unsigned short)pts_tc[i][j] );
-		    }
-		}
-	    }
-	    
-	    start = end;
-	    end = start + 1;
-	}
-    }
-
-    // dump individual triangles if they exist
-    if ( tris_v.size() > 0 ) {
-	int start = 0;
-	int end = 1;
-	string material;
-	while ( start < (int)tri_materials.size() ) {
-	    // find next group
-	    material = tri_materials[start];
-	    while ( (end < (int)tri_materials.size()) && 
-		    (material == tri_materials[end]) &&
-		    3*(end-start) < 32760 )
-	    {
-		// cout << "end = " << end << endl;
-		end++;
-	    }
-	    // cout << "group = " << start << " to " << end - 1 << endl;
-
-	    // write group headers
-	    sgWriteChar( fp, (char)SG_TRIANGLE_FACES ); // type
-	    sgWriteUShort( fp, 2 );		        // nproperties
-	    sgWriteUShort( fp, 1 );                      // nelements
-
-	    sgWriteChar( fp, (char)SG_MATERIAL );       // property
-	    sgWriteUInt( fp, material.length() );        // nbytes
-	    sgWriteBytes( fp, material.length(), material.c_str() );
-
-	    idx_mask = 0;
-	    idx_size = 0;
-	    if ( tris_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; }
-	    if ( tris_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; }
-	    if ( tris_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; }
-	    if ( tris_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size; }
-	    sgWriteChar( fp, (char)SG_INDEX_TYPES );     // property
-	    sgWriteUInt( fp, 1 );                        // nbytes
-	    sgWriteChar( fp, idx_mask );
-
-	    // nbytes
-	    sgWriteUInt( fp, (end - start) * 3 * idx_size
-                             * sizeof(unsigned short) );
-
-	    // write group
-	    for ( i = start; i < end; ++i ) {
-		for ( j = 0; j < 3; ++j ) {
-		    if ( tris_v.size() ) {
-			sgWriteUShort( fp, (unsigned short)tris_v[i][j] );
-		    }
-		    if ( tris_n.size() ) {
-			sgWriteUShort( fp, (unsigned short)tris_n[i][j] );
-		    }
-		    if ( tris_c.size() ) {
-			sgWriteUShort( fp, (unsigned short)tris_c[i][j] );
-		    }
-		    if ( tris_tc.size() ) {
-			sgWriteUShort( fp, (unsigned short)tris_tc[i][j] );
-		    }
-		}
-	    }
-
-	    start = end;
-	    end = start + 1;
-	}
-    }
-
-    // dump triangle strips
-    if ( strips_v.size() > 0 ) {
-	int start = 0;
-	int end = 1;
-	string material;
-	while ( start < (int)strip_materials.size() ) {
-	    // find next group
-	    material = strip_materials[start];
-	    while ( (end < (int)strip_materials.size()) && 
-		    (material == strip_materials[end]) )
-		{
-		    // cout << "end = " << end << endl;
-		    end++;
-		}
-	    // cout << "group = " << start << " to " << end - 1 << endl;
-
-	    // write group headers
-	    sgWriteChar( fp, (char)SG_TRIANGLE_STRIPS ); // type
-	    sgWriteUShort( fp, 2 );		         // nproperties
-	    sgWriteUShort( fp, end - start );             // nelements
-
-	    sgWriteChar( fp, (char)SG_MATERIAL );        // property
-	    sgWriteUInt( fp, material.length() );        // nbytes
-	    sgWriteBytes( fp, material.length(), material.c_str() );
-
-	    idx_mask = 0;
-	    idx_size = 0;
-	    if ( strips_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; }
-	    if ( strips_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; }
-	    if ( strips_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; }
-	    if ( strips_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size;}
-	    sgWriteChar( fp, (char)SG_INDEX_TYPES );     // property
-	    sgWriteUInt( fp, 1 );                        // nbytes
-	    sgWriteChar( fp, idx_mask );
-
-	    // write strips
-	    for ( i = start; i < end; ++i ) {
-		// nbytes
-		sgWriteUInt( fp, strips_v[i].size() * idx_size
-                                 * sizeof(unsigned short));
-		for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
-		    if ( strips_v.size() ) { 
-			sgWriteUShort( fp, (unsigned short)strips_v[i][j] );
-		    }
-		    if ( strips_n.size() ) { 
-			sgWriteUShort( fp, (unsigned short)strips_n[i][j] );
-		    }
-		    if ( strips_c.size() ) { 
-			sgWriteUShort( fp, (unsigned short)strips_c[i][j] );
-		    }
-		    if ( strips_tc.size() ) { 
-			sgWriteUShort( fp, (unsigned short)strips_tc[i][j] );
-		    }
-		}
-	    }
-	    
-	    start = end;
-	    end = start + 1;
-	}
-    }
-
-    // dump triangle fans
-    if ( fans_v.size() > 0 ) {
-	int start = 0;
-	int end = 1;
-	string material;
-	while ( start < (int)fan_materials.size() ) {
-	    // find next group
-	    material = fan_materials[start];
-	    while ( (end < (int)fan_materials.size()) && 
-		    (material == fan_materials[end]) )
-		{
-		    // cout << "end = " << end << endl;
-		    end++;
-		}
-	    // cout << "group = " << start << " to " << end - 1 << endl;
-
-	    // write group headers
-	    sgWriteChar( fp, (char)SG_TRIANGLE_FANS );   // type
-	    sgWriteUShort( fp, 2 );		         // nproperties
-	    sgWriteUShort( fp, end - start );             // nelements
-
-	    sgWriteChar( fp, (char)SG_MATERIAL );       // property
-	    sgWriteUInt( fp, material.length() );        // nbytes
-	    sgWriteBytes( fp, material.length(), material.c_str() );
-
-	    idx_mask = 0;
-	    idx_size = 0;
-	    if ( fans_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; }
-	    if ( fans_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; }
-	    if ( fans_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; }
-	    if ( fans_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size; }
-	    sgWriteChar( fp, (char)SG_INDEX_TYPES );     // property
-	    sgWriteUInt( fp, 1 );                        // nbytes
-	    sgWriteChar( fp, idx_mask );
-
-	    // write fans
-	    for ( i = start; i < end; ++i ) {
-		// nbytes
-		sgWriteUInt( fp, fans_v[i].size() * idx_size
-                                 * sizeof(unsigned short) );
-		for ( j = 0; j < (int)fans_v[i].size(); ++j ) {
-		    if ( fans_v.size() ) {
-			sgWriteUShort( fp, (unsigned short)fans_v[i][j] );
-		    }
-		    if ( fans_n.size() ) {
-			sgWriteUShort( fp, (unsigned short)fans_n[i][j] );
-		    }
-		    if ( fans_c.size() ) {
-			sgWriteUShort( fp, (unsigned short)fans_c[i][j] );
-		    }
-		    if ( fans_tc.size() ) {
-			sgWriteUShort( fp, (unsigned short)fans_tc[i][j] );
-		    }
-		}
-	    }
-	    
-	    start = end;
-	    end = start + 1;
-	}
-    }
-
+    write_objects(fp, SG_POINTS, pts_v, pts_n, pts_c, pts_tc, pt_materials);
+    write_objects(fp, SG_TRIANGLE_FACES, tris_v, tris_n, tris_c, tris_tc, tri_materials);
+    write_objects(fp, SG_TRIANGLE_STRIPS, strips_v, strips_n, strips_c, strips_tc, strip_materials);
+    write_objects(fp, SG_TRIANGLE_FANS, fans_v, fans_n, fans_c, fans_tc, fan_materials);
+    
     // close the file
     gzclose(fp);
 
     if ( sgWriteError() ) {
-	cout << "We detected an error while writing the file." << endl;
-	return false;
+        cout << "Error while writing file " << file.str() << endl;
+        return false;
     }
 
     return true;
@@ -1001,7 +841,7 @@
 // groups come to us sorted by material property.  If not, things
 // don't break, but the result won't be as optimal.
 bool SGBinObject::write_ascii( const string& base, const string& name,
-			       const SGBucket& b )
+                               const SGBucket& b )
 {
     int i, j;
 
@@ -1011,16 +851,16 @@
 
     FILE *fp;
     if ( (fp = fopen( file.c_str(), "w" )) == NULL ) {
-	cout << "ERROR: opening " << file.str() << " for writing!" << endl;
-	return false;
+        cout << "ERROR: opening " << file.str() << " for writing!" << endl;
+        return false;
     }
 
     cout << "triangles size = " << tris_v.size() << "  tri_materials = " 
-	 << tri_materials.size() << endl;
+         << tri_materials.size() << endl;
     cout << "strips size = " << strips_v.size() << "  strip_materials = " 
-	 << strip_materials.size() << endl;
+         << strip_materials.size() << endl;
     cout << "fans size = " << fans_v.size() << "  fan_materials = " 
-	 << fan_materials.size() << endl;
+         << fan_materials.size() << endl;
 
     cout << "points = " << wgs84_nodes.size() << endl;
     cout << "tex coords = " << texcoords.size() << endl;
@@ -1038,22 +878,22 @@
 
     // write bounding sphere
     fprintf(fp, "# gbs %.5f %.5f %.5f %.2f\n",
-	    gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius);
+            gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius);
     fprintf(fp, "\n");
 
     // dump vertex list
     fprintf(fp, "# vertex list\n");
     for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
         SGVec3d p = wgs84_nodes[i] - gbs_center;
-	
-	fprintf(fp,  "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
+        
+        fprintf(fp,  "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
     }
     fprintf(fp, "\n");
 
     fprintf(fp, "# vertex normal list\n");
     for ( i = 0; i < (int)normals.size(); ++i ) {
         SGVec3f p = normals[i];
-	fprintf(fp,  "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
+        fprintf(fp,  "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
     }
     fprintf(fp, "\n");
 
@@ -1061,27 +901,27 @@
     fprintf(fp, "# texture coordinate list\n");
     for ( i = 0; i < (int)texcoords.size(); ++i ) {
         SGVec2f p = texcoords[i];
-	fprintf(fp,  "vt %.5f %.5f\n", p.x(), p.y() );
+        fprintf(fp,  "vt %.5f %.5f\n", p.x(), p.y() );
     }
     fprintf(fp, "\n");
 
     // dump individual triangles if they exist
     if ( tris_v.size() > 0 ) {
-	fprintf(fp, "# triangle groups\n");
-
-	int start = 0;
-	int end = 1;
-	string material;
-	while ( start < (int)tri_materials.size() ) {
-	    // find next group
-	    material = tri_materials[start];
-	    while ( (end < (int)tri_materials.size()) && 
-		    (material == tri_materials[end]) )
-	    {
-		// cout << "end = " << end << endl;
-		end++;
-	    }
-	    // cout << "group = " << start << " to " << end - 1 << endl;
+        fprintf(fp, "# triangle groups\n");
+
+        int start = 0;
+        int end = 1;
+        string material;
+        while ( start < (int)tri_materials.size() ) {
+            // find next group
+            material = tri_materials[start];
+            while ( (end < (int)tri_materials.size()) && 
+                    (material == tri_materials[end]) )
+            {
+                // cout << "end = " << end << endl;
+                end++;
+            }
+            // cout << "group = " << start << " to " << end - 1 << endl;
 
       SGSphered d;
       for ( i = start; i < end; ++i ) {
@@ -1092,44 +932,44 @@
       
       SGVec3d bs_center = d.getCenter();
       double bs_radius = d.getRadius();
-	    
-	    // write group headers
-	    fprintf(fp, "\n");
-	    fprintf(fp, "# usemtl %s\n", material.c_str());
-	    fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
-		    bs_center.x(), bs_center.y(), bs_center.z(), bs_radius);
-
-	    // write groups
-	    for ( i = start; i < end; ++i ) {
-		fprintf(fp, "f");
-		for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
-		    fprintf(fp, " %d/%d", tris_v[i][j], tris_tc[i][j] );
-		}
-		fprintf(fp, "\n");
-	    }
-
-	    start = end;
-	    end = start + 1;
-	}
+            
+            // write group headers
+            fprintf(fp, "\n");
+            fprintf(fp, "# usemtl %s\n", material.c_str());
+            fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
+                    bs_center.x(), bs_center.y(), bs_center.z(), bs_radius);
+
+            // write groups
+            for ( i = start; i < end; ++i ) {
+                fprintf(fp, "f");
+                for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
+                    fprintf(fp, " %d/%d", tris_v[i][j], tris_tc[i][j] );
+                }
+                fprintf(fp, "\n");
+            }
+
+            start = end;
+            end = start + 1;
+        }
     }
 
     // dump triangle groups
     if ( strips_v.size() > 0 ) {
-	fprintf(fp, "# triangle strips\n");
-
-	int start = 0;
-	int end = 1;
-	string material;
-	while ( start < (int)strip_materials.size() ) {
-	    // find next group
-	    material = strip_materials[start];
-	    while ( (end < (int)strip_materials.size()) && 
-		    (material == strip_materials[end]) )
-		{
-		    // cout << "end = " << end << endl;
-		    end++;
-		}
-	    // cout << "group = " << start << " to " << end - 1 << endl;
+        fprintf(fp, "# triangle strips\n");
+
+        int start = 0;
+        int end = 1;
+        string material;
+        while ( start < (int)strip_materials.size() ) {
+            // find next group
+            material = strip_materials[start];
+            while ( (end < (int)strip_materials.size()) && 
+                    (material == strip_materials[end]) )
+                {
+                    // cout << "end = " << end << endl;
+                    end++;
+                }
+            // cout << "group = " << start << " to " << end - 1 << endl;
 
 
       SGSphered d;
@@ -1142,31 +982,53 @@
       SGVec3d bs_center = d.getCenter();
       double bs_radius = d.getRadius();
 
-	    // write group headers
-	    fprintf(fp, "\n");
-	    fprintf(fp, "# usemtl %s\n", material.c_str());
-	    fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
-		    bs_center.x(), bs_center.y(), bs_center.z(), bs_radius);
-
-	    // write groups
-	    for ( i = start; i < end; ++i ) {
-		fprintf(fp, "ts");
-		for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
-		    fprintf(fp, " %d/%d", strips_v[i][j], strips_tc[i][j] );
-		}
-		fprintf(fp, "\n");
-	    }
-	    
-	    start = end;
-	    end = start + 1;
-	}
+            // write group headers
+            fprintf(fp, "\n");
+            fprintf(fp, "# usemtl %s\n", material.c_str());
+            fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
+                    bs_center.x(), bs_center.y(), bs_center.z(), bs_radius);
+
+            // write groups
+            for ( i = start; i < end; ++i ) {
+                fprintf(fp, "ts");
+                for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
+                    fprintf(fp, " %d/%d", strips_v[i][j], strips_tc[i][j] );
+                }
+                fprintf(fp, "\n");
+            }
+            
+            start = end;
+            end = start + 1;
+        }
     }
 
     // close the file
     fclose(fp);
 
     string command = "gzip --force --best " + file.str();
-    system(command.c_str());
-
-    return true;
-}
+    int err = system(command.c_str());
+    if (err)
+    {
+        cout << "ERROR: gzip " << file.str() << " failed!" << endl;
+    }
+
+    return (err == 0);
+}
+
+void SGBinObject::read_properties(gzFile fp, int nproperties)
+{
+    sgSimpleBuffer buf;
+    uint32_t nbytes;
+    
+    // read properties
+    for ( int j = 0; j < nproperties; ++j ) {
+        char prop_type;
+        sgReadChar( fp, &prop_type );
+        sgReadUInt( fp, &nbytes );
+        // cout << "property size = " << nbytes << endl;
+        if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); }
+        char *ptr = buf.get_ptr();
+        sgReadBytes( fp, nbytes, ptr );
+    }
+}
+

Modified: simgear/trunk/simgear/io/sg_binobj.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_binobj.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_binobj.hxx (original)
+++ simgear/trunk/simgear/io/sg_binobj.hxx Sun Jul 15 09:07:01 2012
@@ -27,29 +27,24 @@
 #ifndef _SG_BINOBJ_HXX
 #define _SG_BINOBJ_HXX
 
+#include <zlib.h> // for gzFile
 
 #include <simgear/compiler.h>
 #include <simgear/constants.h>
 #include <simgear/math/sg_types.hxx>
-#include <simgear/bucket/newbucket.hxx>
-
-#include <stdio.h>
-#include <time.h>
-
-#include <list>
+#include <simgear/math/SGMath.hxx>
+
+#include <vector>
 #include <string>
-
-
 
 /** STL Structure used to store object information */
 typedef std::vector < int_list > group_list;
 typedef group_list::iterator group_list_iterator;
 typedef group_list::const_iterator const_group_list_iterator;
 
-
-/** Magic Number for our file format */
-#define SG_FILE_MAGIC_NUMBER  ( ('S'<<24) + ('G'<<16) + SG_BINOBJ_VERSION )
-
+// forward decls
+class SGBucket;
+class SGPath;
 
 /**
  * A class to manipulate the simgear 3d object format.
@@ -85,6 +80,7 @@
  * - vertex: FLOAT, FLOAT, FLOAT
 */
 class SGBinObject {
+private:
     unsigned short version;
 
     SGVec3d gbs_center;
@@ -119,6 +115,24 @@
     group_list fans_tc;		// fans texture coordinate index
     string_list fan_materials;	// fans materials
 
+    void read_properties(gzFile fp, int nproperties);
+    
+    void read_object( gzFile fp,
+                             int obj_type,
+                             int nproperties,
+                             int nelements,
+                             group_list& vertices, 
+                             group_list& normals,
+                             group_list& colors,
+                             group_list& texCoords,
+                             string_list& materials);
+                             
+    void write_header(gzFile fp, int type, int nProps, int nElements);
+    void write_objects(gzFile fp, int type, const group_list& verts,
+        const group_list& normals, const group_list& colors, 
+        const group_list& texCoords, const string_list& materials);
+        
+    unsigned int count_objects(const string_list& materials);
 public:
 
     inline unsigned short get_version() const { return version; }
@@ -206,6 +220,9 @@
      * @return result of write
      */
     bool write_bin( const std::string& base, const std::string& name, const SGBucket& b );
+
+
+    bool write_bin_file(const SGPath& file);
 
     /**
      * Write out the structures to an ASCII file.  We assume that the

Modified: simgear/trunk/simgear/io/sg_file.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_file.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_file.cxx (original)
+++ simgear/trunk/simgear/io/sg_file.cxx Sun Jul 15 09:07:01 2012
@@ -31,6 +31,14 @@
 
 #include <cstring>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#if !defined(_MSC_VER)
+# include <unistd.h>
+#endif
+
 #include <simgear/misc/stdint.hxx>
 #include <simgear/debug/logstream.hxx>
 
@@ -38,13 +46,20 @@
 
 using std::string;
 
-
 SGFile::SGFile(const string &file, int repeat_)
     : file_name(file), fp(-1), eof_flag(true), repeat(repeat_), iteration(0)
 {
     set_type( sgFileType );
 }
 
+SGFile::SGFile( int existingFd ) :
+    fp(existingFd),
+    eof_flag(false),
+    repeat(1),
+    iteration(0)
+{
+    set_type( sgFileType );
+}
 
 SGFile::~SGFile() {
 }

Modified: simgear/trunk/simgear/io/sg_file.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_file.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_file.hxx (original)
+++ simgear/trunk/simgear/io/sg_file.hxx Sun Jul 15 09:07:01 2012
@@ -26,25 +26,11 @@
 #ifndef _SG_FILE_HXX
 #define _SG_FILE_HXX
 
-
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
 #include <simgear/compiler.h>
 
 #include <string>
 
-#include <sys/types.h>		// for open(), read(), write(), close()
-#include <sys/stat.h>		// for open(), read(), write(), close()
-#include <fcntl.h>		// for open(), read(), write(), close()
-#if !defined( _MSC_VER )
-#  include <unistd.h>		// for open(), read(), write(), close()
-#endif
-
 #include "iochannel.hxx"
-
-using std::string;
 
 
 /**
@@ -52,7 +38,7 @@
  */
 class SGFile : public SGIOChannel {
 
-    string file_name;
+    std::string file_name;
     int fp;
     bool eof_flag;
     // Number of repetitions to play. -1 means loop infinitely.
@@ -70,7 +56,12 @@
      * @param file name of file to open
      * @param repeat On eof restart at the beginning of the file
      */
-    SGFile( const string& file, int repeat_ = 1 );
+    SGFile( const std::string& file, int repeat_ = 1 );
+
+    /**
+     * Create an SGFile from an existing, open file-descriptor
+     */
+    SGFile( int existingFd );
 
     /** Destructor */
     ~SGFile();
@@ -94,10 +85,10 @@
     bool close();
 
     /** @return the name of the file being manipulated. */
-    inline string get_file_name() const { return file_name; }
+    inline std::string get_file_name() const { return file_name; }
 
     /** @return true of eof conditions exists */
-    inline bool eof() const { return eof_flag; };
+    virtual bool eof() const { return eof_flag; };
 };
 
 

Modified: simgear/trunk/simgear/io/sg_netChannel.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_netChannel.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_netChannel.cxx (original)
+++ simgear/trunk/simgear/io/sg_netChannel.cxx Sun Jul 15 09:07:01 2012
@@ -34,8 +34,10 @@
 #include <memory>
 #include <cassert>
 #include <cstring>
+#include <errno.h>
 
 #include <simgear/debug/logstream.hxx>
+
 
 namespace simgear  {
 
@@ -45,6 +47,7 @@
 {
   closed = true ;
   connected = false ;
+  resolving_host  = false;
   accepting = false ;
   write_blocked = false ;
   should_delete = false ;
@@ -82,7 +85,6 @@
   close () ;
   Socket::setHandle ( handle ) ;
   connected = is_connected ;
-  //if ( connected ) this->handleConnect();
   closed = false ;
 }
 
@@ -106,21 +108,12 @@
 }
 
 int
-NetChannel::connect ( const char* host, int port )
-{
-  int result = Socket::connect ( host, port ) ;
-  if (result == 0) {
-    connected = true ;
-    //this->handleConnect();
-    return 0;
-  } else if (isNonBlockingError ()) {
-    return 0;
-  } else {
-    // some other error condition
-    this->handleError (result);
-    close();
-    return -1;
-  }
+NetChannel::connect ( const char* h, int p )
+{
+  host = h;
+  port = p;
+  resolving_host = true;
+  return handleResolve();
 }
 
 int
@@ -188,12 +181,10 @@
   if (accepting) {
     if (!connected) {
       connected = true ;
-      //this->handleConnect();
     }
     this->handleAccept();
   } else if (!connected) {
     connected = true ;
-    //this->handleConnect();
     this->handleRead();
   } else {
     this->handleRead();
@@ -205,10 +196,40 @@
 {
   if (!connected) {
     connected = true ;
-    //this->handleConnect();
   }
   write_blocked = false ;
   this->handleWrite();
+}
+
+int
+NetChannel::handleResolve()
+{
+    IPAddress addr;
+    if (!IPAddress::lookupNonblocking(host.c_str(), addr)) {
+        return 0; // not looked up yet, wait longer
+    }
+    
+    if (!addr.isValid()) {
+        SG_LOG(SG_IO, SG_WARN, "Network: host lookup failed:" << host);
+        handleError (0);
+        close();
+        return -1;
+    }
+    
+    resolving_host = false;
+    addr.setPort(port);
+    int result = Socket::connect ( &addr ) ;
+    if (result == 0) {
+        connected = true ;
+        return 0;
+    } else if (isNonBlockingError ()) {
+        return 0;
+    } else {
+        // some other error condition
+        handleError (result);
+        close();
+        return -1;
+    }
 }
 
 bool
@@ -235,6 +256,12 @@
     }
     else if ( ! ch -> closed )
     {
+      if (ch -> resolving_host )
+      {
+          ch -> handleResolve();
+          continue;
+      }
+      
       nopen++ ;
       if (ch -> readable()) {
         assert(nreads<MAX_SOCKETS);

Modified: simgear/trunk/simgear/io/sg_netChannel.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_netChannel.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_netChannel.hxx (original)
+++ simgear/trunk/simgear/io/sg_netChannel.hxx Sun Jul 15 09:07:01 2012
@@ -54,14 +54,17 @@
 #define SG_NET_CHANNEL_H
 
 #include <simgear/io/raw_socket.hxx>
+#include <string>
 
 namespace simgear
 {
 
 class NetChannel : public Socket
 {
-  bool closed, connected, accepting, write_blocked, should_delete ;
+  bool closed, connected, accepting, write_blocked, should_delete, resolving_host ;
   NetChannel* next_channel ;
+  std::string host;
+  int port;
   
   friend bool netPoll (unsigned int timeout);
 
@@ -96,6 +99,7 @@
   
   void handleReadEvent (void);
   void handleWriteEvent (void);
+  int handleResolve (void);
   
 // These are meant to be overridden.
   virtual void handleClose (void) {

Modified: simgear/trunk/simgear/io/sg_netChat.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_netChat.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_netChat.cxx (original)
+++ simgear/trunk/simgear/io/sg_netChat.cxx Sun Jul 15 09:07:01 2012
@@ -26,20 +26,31 @@
 #include <simgear/io/sg_netChat.hxx>
 
 #include <cstring> // for strdup
+#include <cstdlib>
 
 namespace  simgear {
 
 void
 NetChat::setTerminator (const char* t)
 {
-  if (terminator) delete[] terminator;
+  if (terminator) free(terminator);
   terminator = strdup(t);
+  bytesToCollect = -1;
 }
 
 const char*
 NetChat::getTerminator (void)
 {
   return terminator;
+}
+
+
+void
+NetChat::setByteCount(int count)
+{
+    if (terminator) free(terminator);
+    terminator = NULL;
+    bytesToCollect = count;
 }
 
 // return the size of the largest prefix of needle at the end
@@ -89,13 +100,23 @@
   // necessary because we might read several data+terminator combos
   // with a single recv().
   
-  while (in_buffer.getLength()) {
-
+  while (in_buffer.getLength()) {      
     // special case where we're not using a terminator
-    if (terminator == 0 || *terminator == 0) {
-      collectIncomingData (in_buffer.getData(),in_buffer.getLength());
-      in_buffer.remove ();
-      return;
+    if (terminator == 0 || *terminator == 0) {        
+        if ( bytesToCollect > 0) {
+            const int toRead = std::min(in_buffer.getLength(), bytesToCollect);
+            collectIncomingData(in_buffer.getData(), toRead);
+            in_buffer.remove(0, toRead);
+            bytesToCollect -= toRead;
+            if (bytesToCollect ==  0) { // read all requested bytes
+                foundTerminator();
+            }
+        } else { // read the whole lot
+            collectIncomingData (in_buffer.getData(),in_buffer.getLength());
+            in_buffer.remove ();
+        }
+        
+        continue;
     }
     
     int terminator_len = strlen(terminator);

Modified: simgear/trunk/simgear/io/sg_netChat.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_netChat.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_netChat.hxx (original)
+++ simgear/trunk/simgear/io/sg_netChat.hxx Sun Jul 15 09:07:01 2012
@@ -61,6 +61,8 @@
 #ifndef SG_NET_CHAT_H
 #define SG_NET_CHAT_H
 
+#include <memory>
+#include <cstdlib>
 #include <simgear/io/sg_netBuffer.hxx>
 
 namespace simgear
@@ -69,15 +71,24 @@
 class NetChat : public NetBufferChannel
 {
   char* terminator;
-  
+  int bytesToCollect;
   virtual void handleBufferRead (NetBuffer& buffer) ;
 
 public:
 
-  NetChat () : terminator (0) {}
+  NetChat () : 
+    terminator (NULL),
+    bytesToCollect(-1) 
+  {}
 
   void setTerminator (const char* t);
   const char* getTerminator (void);
+
+  /**
+   * set byte count to collect - 'foundTerminator' will be called once
+   * this many bytes have been collected
+   */
+  void setByteCount(int bytes);
 
   bool push (const char* s);
   

Modified: simgear/trunk/simgear/io/sg_socket.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_socket.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_socket.cxx (original)
+++ simgear/trunk/simgear/io/sg_socket.cxx Sun Jul 15 09:07:01 2012
@@ -36,6 +36,7 @@
 #include "sg_socket.hxx"
 
 bool SGSocket::init = false;
+using std::string;
 
 SGSocket::SGSocket( const string& host, const string& port_, 
 		    const string& style ) :

Modified: simgear/trunk/simgear/io/sg_socket_udp.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_socket_udp.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_socket_udp.cxx (original)
+++ simgear/trunk/simgear/io/sg_socket_udp.cxx Sun Jul 15 09:07:01 2012
@@ -32,6 +32,8 @@
 
 #include <cstring>
 #include <cstdlib> // for atoi
+
+using std::string;
 
 SGSocketUDP::SGSocketUDP( const string& host, const string& port ) :
     hostname(host),
@@ -160,11 +162,8 @@
 	return 0;
     }
 
-    bool error_condition = false;
-
     if ( sock.send( buf, length, 0 ) < 0 ) {
 	SG_LOG( SG_IO, SG_WARN, "Error writing to socket: " << port );
-	error_condition = true;
 	return 0;
     }
 

Modified: simgear/trunk/simgear/io/sg_socket_udp.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/io/sg_socket_udp.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/io/sg_socket_udp.hxx (original)
+++ simgear/trunk/simgear/io/sg_socket_udp.hxx Sun Jul 15 09:07:01 2012
@@ -89,7 +89,7 @@
      * @param host name of host if direction is SG_IO_OUT or SG_IO_BI
      * @param port port number if we care to choose one.
      * @param style specify "udp" or "tcp" */
-    SGSocketUDP( const string& host, const string& port );
+    SGSocketUDP( const std::string& host, const std::string& port );
 
     /** Destructor */
     ~SGSocketUDP();

Modified: simgear/trunk/simgear/magvar/testmagvar.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/magvar/testmagvar.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/magvar/testmagvar.cxx (original)
+++ simgear/trunk/simgear/magvar/testmagvar.cxx Sun Jul 15 09:07:01 2012
@@ -16,7 +16,7 @@
   /* output N, E, down components of B (nTesla)
      dip angle (down positive), variation (E positive) */
 double lat_deg,lon_deg,h,var;
-int model,yy,mm,dd;
+int /* model,*/yy,mm,dd;
 double field[6];
 
 if ((argc != 8) && (argc !=7)) {
@@ -36,9 +36,9 @@
 dd=     (int)strtol(argv[5],NULL,10);
 yy=     (int)strtol(argv[6],NULL,10);
 if (argc == 8){
-  model=  (int)strtol(argv[7],NULL,10);
+//  model=  (int)strtol(argv[7],NULL,10);
 }else{
-  model=7;
+//  model=7;
 }
 
 

Modified: simgear/trunk/simgear/math/SGBox.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/math/SGBox.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/math/SGBox.hxx (original)
+++ simgear/trunk/simgear/math/SGBox.hxx Sun Jul 15 09:07:01 2012
@@ -97,7 +97,7 @@
     return (_max[0] - _min[0])*(_max[1] - _min[1])*(_max[2] - _min[2]);
   }
 
-  const bool empty() const
+  bool empty() const
   { return !valid(); }
 
   bool valid() const

Modified: simgear/trunk/simgear/math/SGGeod.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/math/SGGeod.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/math/SGGeod.cxx (original)
+++ simgear/trunk/simgear/math/SGGeod.cxx Sun Jul 15 09:07:01 2012
@@ -14,6 +14,10 @@
 // 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 "SGMath.hxx"
 

Modified: simgear/trunk/simgear/math/SGMathTest.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/math/SGMathTest.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/math/SGMathTest.cxx (original)
+++ simgear/trunk/simgear/math/SGMathTest.cxx Sun Jul 15 09:07:01 2012
@@ -22,9 +22,8 @@
 #include <cstdlib>
 #include <iostream>
 
-#include <plib/sg.h>
-
 #include "SGMath.hxx"
+#include "sg_random.h"
 
 template<typename T>
 bool
@@ -202,6 +201,34 @@
 
 template<typename T>
 bool
+QuatDerivativeTest(void)
+{
+  for (unsigned i = 0; i < 100; ++i) {
+    // Generate the test case:
+    // Give a lower bound to the distance, so avoid testing cancelation
+    T dt = T(0.01) + sg_random();
+    // Start with orientation o0, angular velocity av and a random stepsize
+    SGQuat<T> o0 = SGQuat<T>::fromEulerDeg(T(360)*sg_random(), T(360)*sg_random(), T(360)*sg_random());
+    SGVec3<T> av(sg_random(), sg_random(), sg_random());
+    // Do one euler step and renormalize
+    SGQuat<T> o1 = normalize(o0 + dt*o0.derivative(av));
+
+    // Check if we can restore the angular velocity
+    SGVec3<T> av2 = SGQuat<T>::forwardDifferenceVelocity(o0, o1, dt);
+    if (!equivalent(av, av2))
+      return false;
+
+    // Test with the equivalent orientation
+    o1 = -o1;
+    av2 = SGQuat<T>::forwardDifferenceVelocity(o0, o1, dt);
+    if (!equivalent(av, av2))
+      return false;
+  }
+  return true;
+}
+
+template<typename T>
+bool
 MatrixTest(void)
 {
   // Create some test matrix
@@ -275,17 +302,17 @@
   // uses examples from Williams aviation formulary
   SGGeoc lax = SGGeoc::fromRadM(-2.066470, 0.592539, 10.0);
   SGGeoc jfk = SGGeoc::fromRadM(-1.287762, 0.709186, 10.0);
-  
+
   double distNm = SGGeodesy::distanceRad(lax, jfk) * SG_RAD_TO_NM;
   std::cout << "distance is " << distNm << std::endl;
   if (0.5 < fabs(distNm - 2144)) // 2144 nm
 	return false;
-	
+
   double crsDeg = SGGeodesy::courseRad(lax, jfk) * SG_RADIANS_TO_DEGREES;
   std::cout << "course is " << crsDeg << std::endl;
   if (0.5 < fabs(crsDeg - 66)) // 66 degrees
 	return false;
-	
+
   SGGeoc adv;
   SGGeodesy::advanceRadM(lax, crsDeg * SG_DEGREES_TO_RADIANS, 100 * SG_NM_TO_METER, adv);
   std::cout << "lon:" << adv.getLongitudeRad() << ", lat:" << adv.getLatitudeRad() << std::endl;
@@ -300,6 +327,8 @@
 int
 main(void)
 {
+  sg_srandom(17);
+
   // Do vector tests
   if (!Vec3Test<float>())
     return EXIT_FAILURE;
@@ -311,6 +340,10 @@
     return EXIT_FAILURE;
   if (!QuatTest<double>())
     return EXIT_FAILURE;
+  if (!QuatDerivativeTest<float>())
+    return EXIT_FAILURE;
+  if (!QuatDerivativeTest<double>())
+    return EXIT_FAILURE;
 
   // Do matrix tests
   if (!MatrixTest<float>())

Modified: simgear/trunk/simgear/math/SGQuat.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/math/SGQuat.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/math/SGQuat.hxx (original)
+++ simgear/trunk/simgear/math/SGQuat.hxx Sun Jul 15 09:07:01 2012
@@ -230,7 +230,7 @@
     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);
@@ -279,7 +279,7 @@
       xRad = 0;
     else
       xRad = atan2(num, den);
-    
+
     T tmp = 2*(x()*z() - w()*y());
     if (tmp <= -1)
       yRad = T(0.5)*SGMisc<T>::pi();
@@ -287,8 +287,8 @@
       yRad = -T(0.5)*SGMisc<T>::pi();
     else
       yRad = -asin(tmp);
-   
-    num = 2*(x()*y() + w()*z()); 
+
+    num = 2*(x()*y() + w()*z());
     den = sqrQW + sqrQX - sqrQY - sqrQZ;
     if (fabs(den) <= SGLimits<T>::min() &&
         fabs(num) <= SGLimits<T>::min())
@@ -323,7 +323,7 @@
       T sAng = sin(angle);
       if (fabs(sAng) <= SGLimits<T>::min())
         axis = SGVec3<T>(1, 0, 0);
-      else 
+      else
         axis = (rNrm/sAng)*imag(*this);
       angle *= 2;
     }
@@ -449,8 +449,44 @@
     deriv.x() = T(0.5)*( w()*angVel(0) - z()*angVel(1) + y()*angVel(2));
     deriv.y() = T(0.5)*( z()*angVel(0) + w()*angVel(1) - x()*angVel(2));
     deriv.z() = T(0.5)*(-y()*angVel(0) + x()*angVel(1) + w()*angVel(2));
-    
+
     return deriv;
+  }
+
+  /// Return the angular velocity w that makes q0 translate to q1 using
+  /// an explicit euler step with stepsize h.
+  /// That is, look for an w where
+  /// q1 = normalize(q0 + h*q0.derivative(w))
+  static SGVec3<T>
+  forwardDifferenceVelocity(const SGQuat& q0, const SGQuat& q1, const T& h)
+  {
+    // Let D_q0*w = q0.derivative(w), D_q0 the above 4x3 matrix.
+    // Then D_q0^t*D_q0 = 0.25*Id and D_q0*q0 = 0.
+    // Let lambda be a nonzero normailzation factor, then
+    //  q1 = normalize(q0 + h*q0.derivative(w))
+    // can be rewritten
+    //  lambda*q1 = q0 + h*D_q0*w.
+    // Multiply left by the transpose D_q0^t and reorder gives
+    //  4*lambda/h*D_q0^t*q1 = w.
+    // Now compute lambda by substitution of w into the original
+    // equation
+    //  lambda*q1 = q0 + 4*lambda*D_q0*D_q0^t*q1,
+    // multiply by q1^t from the left
+    //  lambda*<q1,q1> = <q0,q1> + 4*lambda*<D_q0^t*q1,D_q0^t*q1>
+    // and solving for lambda gives
+    //  lambda = <q0,q1>/(1 - 4*<D_q0^t*q1,D_q0^t*q1>).
+
+    // The transpose of the derivative matrix
+    // the 0.5 factor is handled below
+    // also note that the initializer uses x, y, z, w instead of w, x, y, z
+    SGQuat d0(q0.w(), q0.z(), -q0.y(), -q0.x());
+    SGQuat d1(-q0.z(), q0.w(), q0.x(), -q0.y());
+    SGQuat d2(q0.y(), -q0.x(), q0.w(), -q0.z());
+    // 2*D_q0^t*q1
+    SGVec3<T> Dq(dot(d0, q1), dot(d1, q1), dot(d2, q1));
+    // Like above, but take into account that Dq = 2*D_q0^t*q1
+    T lambda = dot(q0, q1)/(T(1) - dot(Dq, Dq));
+    return (2*lambda/h)*Dq;
   }
 
 private:
@@ -478,7 +514,7 @@
 
     // 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 
+    // It is even more, we can see from the above formula that
     // sqrt(0.5) < cos05ang.
 
 

Modified: simgear/trunk/simgear/math/SGSphere.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/math/SGSphere.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/math/SGSphere.hxx (original)
+++ simgear/trunk/simgear/math/SGSphere.hxx Sun Jul 15 09:07:01 2012
@@ -18,10 +18,22 @@
 #ifndef SGSphere_H
 #define SGSphere_H
 
+
 template<typename T>
 class SGSphere {
 public:
+
+#ifdef __GNUC__
+// Avoid "_center not initialized" warnings.
+#   pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+
   SGSphere() :
+     /*
+      * Do not initialize _center to save unneeded initialization time.
+      * Fix 'may be used uninitialized' warnings locally instead
+      */
+//  _center(0.0, 0.0, 0.0),
     _radius(-1)
   { }
   SGSphere(const SGVec3<T>& center, const T& radius) :
@@ -33,6 +45,11 @@
     _center(sphere.getCenter()),
     _radius(sphere.getRadius())
   { }
+
+#ifdef __GNUC__
+  // Restore warning settings.
+#   pragma GCC diagnostic warning "-Wuninitialized"
+#endif
 
   const SGVec3<T>& getCenter() const
   { return _center; }

Modified: simgear/trunk/simgear/math/SGVec3.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/math/SGVec3.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/math/SGVec3.hxx (original)
+++ simgear/trunk/simgear/math/SGVec3.hxx Sun Jul 15 09:07:01 2012
@@ -29,6 +29,11 @@
 public:
   typedef T value_type;
 
+#ifdef __GNUC__
+// Avoid "_data not initialized" warnings (see comment below).
+#   pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+
   /// Default constructor. Does not initialize at all.
   /// If you need them zero initialized, use SGVec3::zeros()
   SGVec3(void)
@@ -41,6 +46,12 @@
       data()[i] = SGLimits<T>::quiet_NaN();
 #endif
   }
+
+#ifdef __GNUC__
+  // Restore warning settings.
+#   pragma GCC diagnostic warning "-Wuninitialized"
+#endif
+
   /// Constructor. Initialize by the given values
   SGVec3(T x, T y, T z)
   { data()[0] = x; data()[1] = y; data()[2] = z; }

Modified: simgear/trunk/simgear/math/sg_random.h
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/math/sg_random.h?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/math/sg_random.h (original)
+++ simgear/trunk/simgear/math/sg_random.h Sun Jul 15 09:07:01 2012
@@ -40,7 +40,7 @@
  * Structure to hold MT algorithm state to easily allow independant
  * sets of random numbers with different seeds.
  */
-struct {unsigned int array[MT_N]; int index; } typedef mt;
+typedef struct {unsigned int array[MT_N]; int index; } mt;
 
 /**
  * Initialize a new MT state with a given seed.

Modified: simgear/trunk/simgear/misc/interpolator.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/interpolator.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/interpolator.cxx (original)
+++ simgear/trunk/simgear/misc/interpolator.cxx Sun Jul 15 09:07:01 2012
@@ -15,6 +15,10 @@
 // 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 "interpolator.hxx"
 

Modified: simgear/trunk/simgear/misc/sg_dir.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/sg_dir.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/sg_dir.cxx (original)
+++ simgear/trunk/simgear/misc/sg_dir.cxx Sun Jul 15 09:07:01 2012
@@ -18,33 +18,104 @@
 //
 // $Id$
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
 
 #include <simgear/misc/sg_dir.hxx>
 
 #ifdef _WIN32
 #  define WIN32_LEAN_AND_MEAN
 #  include <windows.h>
+#  include <direct.h>
 #else
 #  include <sys/types.h>
 #  include <dirent.h>
+#  include <sys/stat.h>
+#  include <unistd.h>
+#  include <errno.h>
 #endif
 
 #include <simgear/debug/logstream.hxx>
+#include <boost/foreach.hpp>
 
 #include <cstring>
 #include <iostream>
 
+using std::string;
+
 namespace simgear
 {
 
+Dir::Dir() :
+    _removeOnDestroy(false)
+{
+}
+
 Dir::Dir(const SGPath& path) :
-  _path(path)
-{
+  _path(path),
+  _removeOnDestroy(false)
+{
+    _path.set_cached(false); // disable caching, so create/remove work
 }
 
 Dir::Dir(const Dir& rel, const SGPath& relPath) :
-  _path(rel.file(relPath.str()))
-{
+  _path(rel.file(relPath.str())),
+  _removeOnDestroy(false)
+{
+    _path.set_cached(false); // disable caching, so create/remove work
+}
+
+Dir::~Dir()
+{
+    if (_removeOnDestroy) {
+        remove(true);
+    }
+}
+
+void Dir::setRemoveOnDestroy()
+{
+    _removeOnDestroy = true;
+}
+
+Dir Dir::current()
+{
+#ifdef _WIN32
+    char* buf = _getcwd(NULL, 0);
+#else
+    char* buf = ::getcwd(NULL, 0);
+#endif
+    SGPath p(buf);
+    free(buf);
+    return Dir(p);
+}
+
+Dir Dir::tempDir(const std::string& templ)
+{
+#ifdef HAVE_MKDTEMP
+    char buf[1024];
+    const char* tempPath = ::getenv("TMPDIR");
+    if (!tempPath) {
+        tempPath = "/tmp/";
+    }
+    // Mac OS-X / BSD manual says any number of 'X's, but GLibc manual
+    // says exactly six, so that's what I'm going with
+    ::snprintf(buf, 1024, "%s%s-XXXXXX", tempPath, templ.c_str());
+    if (!mkdtemp(buf)) {
+        SG_LOG(SG_IO, SG_WARN, "mkdtemp failed:" << strerror(errno));
+        return Dir();
+    }
+    
+    return Dir(SGPath(buf));
+#else
+    SGPath p(tempnam(0, templ.c_str()));
+    Dir t(p);
+    if (!t.create(0700)) {
+        SG_LOG(SG_IO, SG_WARN, "failed to create temporary directory at " << p.str());
+    }
+    
+    return t;
+#endif
 }
 
 PathList Dir::children(int types, const std::string& nameFilter) const
@@ -115,7 +186,8 @@
     }
     
     // skip hidden files (names beginning with '.') unless requested
-    if (!(types & INCLUDE_HIDDEN) && (entry->d_name[0] == '.')) {
+    if (!(types & INCLUDE_HIDDEN) && (entry->d_name[0] == '.') &&
+         strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
       continue;
     }
     
@@ -174,8 +246,79 @@
 SGPath Dir::file(const std::string& name) const
 {
   SGPath childPath = _path;
+  childPath.set_cached(true);
   childPath.append(name);
   return childPath;  
 }
 
+#ifdef _WIN32
+#  define sgMkDir(d,m)       _mkdir(d)
+#else
+#  define sgMkDir(d,m)       mkdir(d,m)
+#endif
+
+bool Dir::create(mode_t mode)
+{
+    if (exists()) {
+        return false; // already exists
+    }
+    
+// recursively create parent directories
+    Dir pr(parent());
+    if (!pr.path().isNull() && !pr.exists()) {
+        bool ok = pr.create(mode);
+        if (!ok) {
+            return false;
+        }
+    }
+    
+// finally, create ourselves
+    int err = sgMkDir(_path.c_str(), mode);
+    if (err) {
+        SG_LOG(SG_IO, SG_WARN,  "directory creation failed: (" << _path.str() << ") " << strerror(errno) );
+    }
+    
+    return (err == 0);
+}
+
+bool Dir::remove(bool recursive)
+{
+    if (!exists()) {
+        SG_LOG(SG_IO, SG_WARN, "attempt to remove non-existant dir:" << _path.str());
+        return false;
+    }
+    
+    if (recursive) {
+        bool ok;
+        PathList cs = children(NO_DOT_OR_DOTDOT | INCLUDE_HIDDEN | TYPE_FILE | TYPE_DIR);
+        BOOST_FOREACH(SGPath path, cs) {
+            if (path.isDir()) {
+                Dir childDir(path);
+                ok = childDir.remove(true);
+            } else {
+                ok = path.remove();
+            }
+            
+            if (!ok) {
+                return false;
+            }
+        } // of child iteration
+    } // of recursive deletion
+    
+#ifdef _WIN32
+    int err = _rmdir(_path.c_str());
+#else
+    int err = rmdir(_path.c_str());
+#endif
+    if (err) {
+        SG_LOG(SG_IO, SG_WARN, "rmdir failed:" << _path.str() << ":" << strerror(errno));
+    }
+    return (err == 0);
+}
+
+Dir Dir::parent() const
+{
+    return Dir(_path.dir());
+}
+
 } // of namespace simgear

Modified: simgear/trunk/simgear/misc/sg_dir.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/sg_dir.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/sg_dir.hxx (original)
+++ simgear/trunk/simgear/misc/sg_dir.hxx Sun Jul 15 09:07:01 2012
@@ -31,6 +31,10 @@
 #include <simgear/math/sg_types.hxx>
 #include <simgear/misc/sg_path.hxx>
 
+#ifdef _MSC_VER
+  typedef int mode_t;
+#endif
+
 namespace simgear
 {
   typedef std::vector<SGPath> PathList;
@@ -38,6 +42,23 @@
   class Dir
   {
   public:
+    Dir();
+    ~Dir();
+    
+    /**
+     * when this directory object is destroyed, remove the corresponding
+     * diretory (and its contents) from the disk. Often used with temporary
+     * directories to ensure they are cleaned up.
+     */
+    void setRemoveOnDestroy();
+    
+    static Dir current();
+    
+    /**
+     * create a temporary directory, using the supplied name
+     */
+    static Dir tempDir(const std::string& templ);
+      
     Dir(const SGPath& path);
     Dir(const Dir& rel, const SGPath& relPath);
     
@@ -53,12 +74,34 @@
     
     SGPath file(const std::string& name) const;
     
+    SGPath path() const
+        { return _path; }
+    
+    /**
+     * create the directory (and any parents as required) with the
+     * request mode, or return failure
+     */
+    bool create(mode_t mode);
+    
+    /**
+     * remove the directory. 
+     * If recursive is true, contained files and directories are
+     * recursively removed
+     */
+    bool remove(bool recursive = false);
+    
     /**
      * Check that the directory at the path exists (and is a directory!)
      */
     bool exists() const;
+    
+    /**
+     * parent directory, if one exists
+     */
+    Dir parent() const;
   private:
     mutable SGPath _path;
+    bool _removeOnDestroy;
   };
 } // of namespace simgear
 

Modified: simgear/trunk/simgear/misc/sg_path.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/sg_path.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/sg_path.cxx (original)
+++ simgear/trunk/simgear/misc/sg_path.cxx Sun Jul 15 09:07:01 2012
@@ -28,13 +28,16 @@
 #include <simgear/debug/logstream.hxx>
 #include <stdio.h>
 #include <sys/stat.h>
+#include <errno.h>
+
 #ifdef _WIN32
 #  include <direct.h>
 #endif
 #include "sg_path.hxx"
 
+#include <boost/algorithm/string/case_conv.hpp>
+
 using std::string;
-
 
 /**
  * define directory path separators
@@ -50,22 +53,20 @@
 #endif
 
 
-// If Unix, replace all ":" with "/".  In windoze, allow the
-// second character to be a ":" for things like c:\foo\bar
-
+// For windows, replace "\" by "/".
 void
 SGPath::fix()
 {
-    for ( string::size_type i = 0; i < path.size(); ++i ) {
-#if defined( WIN32 )
-	// for windoze, don't replace the ":" for the second character
-	if ( i == 1 ) {
-	    continue;
-	}
-#endif
-	if ( path[i] == sgDirPathSepBad ) {
-	    path[i] = sgDirPathSep;
-	}
+    string::size_type sz = path.size();
+    for ( string::size_type i = 0; i < sz; ++i ) {
+        if ( path[i] == sgDirPathSepBad ) {
+            path[i] = sgDirPathSep;
+        }
+    }
+    // drop trailing "/"
+    while ((sz>1)&&(path[sz-1]==sgDirPathSep))
+    {
+        path.resize(--sz);
     }
 }
 
@@ -73,7 +74,8 @@
 // default constructor
 SGPath::SGPath()
     : path(""),
-    _cached(false)
+    _cached(false),
+    _cacheEnabled(true)
 {
 }
 
@@ -81,7 +83,8 @@
 // create a path based on "path"
 SGPath::SGPath( const std::string& p )
     : path(p),
-    _cached(false)
+    _cached(false),
+    _cacheEnabled(true)
 {
     fix();
 }
@@ -89,7 +92,8 @@
 // create a path based on "path" and a "subpath"
 SGPath::SGPath( const SGPath& p, const std::string& r )
     : path(p.path),
-    _cached(false)
+    _cached(false),
+    _cacheEnabled(p._cacheEnabled)
 {
     append(r);
     fix();
@@ -98,19 +102,23 @@
 SGPath::SGPath(const SGPath& p) :
   path(p.path),
   _cached(p._cached),
+  _cacheEnabled(p._cacheEnabled),
   _exists(p._exists),
   _isDir(p._isDir),
-  _isFile(p._isFile)
-{
-}
-    
+  _isFile(p._isFile),
+  _modTime(p._modTime)
+{
+}
+
 SGPath& SGPath::operator=(const SGPath& p)
 {
   path = p.path;
   _cached = p._cached;
+  _cacheEnabled = p._cacheEnabled;
   _exists = p._exists;
   _isDir = p._isDir;
   _isFile = p._isFile;
+  _modTime = p._modTime;
   return *this;
 }
 
@@ -126,16 +134,20 @@
     _cached = false;
 }
 
+void SGPath::set_cached(bool cached)
+{
+    _cacheEnabled = cached;
+}
 
 // append another piece to the existing path
 void SGPath::append( const string& p ) {
     if ( path.size() == 0 ) {
-	path = p;
-    } else {
-	if ( p[0] != sgDirPathSep ) {
-	    path += sgDirPathSep;
-	}
-	path += p;
+        path = p;
+    } else {
+    if ( p[0] != sgDirPathSep ) {
+        path += sgDirPathSep;
+    }
+        path += p;
     }
     fix();
     _cached = false;
@@ -151,9 +163,9 @@
 // path separator
 void SGPath::concat( const string& p ) {
     if ( path.size() == 0 ) {
-	path = p;
-    } else {
-	path += p;
+        path = p;
+    } else {
+        path += p;
     }
     fix();
     _cached = false;
@@ -161,12 +173,13 @@
 
 
 // Get the file part of the path (everything after the last path sep)
-string SGPath::file() const {
-    int index = path.rfind(sgDirPathSep);
-    if (index >= 0) {
-	return path.substr(index + 1);
-    } else {
-	return "";
+string SGPath::file() const
+{
+    string::size_type index = path.rfind(sgDirPathSep);
+    if (index != string::npos) {
+        return path.substr(index + 1);
+    } else {
+        return path;
     }
 }
   
@@ -175,20 +188,45 @@
 string SGPath::dir() const {
     int index = path.rfind(sgDirPathSep);
     if (index >= 0) {
-	return path.substr(0, index);
-    } else {
-	return "";
+        return path.substr(0, index);
+    } else {
+        return "";
     }
 }
 
 // get the base part of the path (everything but the extension.)
-string SGPath::base() const {
-    int index = path.rfind(".");
-    if ((index >= 0) && (path.find("/", index) == string::npos)) {
-	return path.substr(0, index);
-    } else {
-	return "";
-    }
+string SGPath::base() const
+{
+    string::size_type index = path.rfind(".");
+    string::size_type lastSep = path.rfind(sgDirPathSep);
+    
+// tolerate dots inside directory names
+    if ((lastSep != string::npos) && (index < lastSep)) {
+        return path;
+    }
+    
+    if (index != string::npos) {
+        return path.substr(0, index);
+    } else {
+        return path;
+    }
+}
+
+string SGPath::file_base() const
+{
+    string::size_type index = path.rfind(sgDirPathSep);
+    if (index == string::npos) {
+        index = 0; // no separator in the name
+    } else {
+        ++index; // skip past the separator
+    }
+    
+    string::size_type firstDot = path.find(".", index);
+    if (firstDot == string::npos) {
+        return path.substr(index); // no extensions
+    }
+    
+    return path.substr(index, firstDot - index);
 }
 
 // get the extension (everything after the final ".")
@@ -197,15 +235,36 @@
 string SGPath::extension() const {
     int index = path.rfind(".");
     if ((index >= 0)  && (path.find("/", index) == string::npos)) {
-	return path.substr(index + 1);
-    } else {
-	return "";
+        return path.substr(index + 1);
+    } else {
+        return "";
+    }
+}
+
+string SGPath::lower_extension() const {
+    return boost::to_lower_copy(extension());
+}
+
+string SGPath::complete_lower_extension() const
+{
+    string::size_type index = path.rfind(sgDirPathSep);
+    if (index == string::npos) {
+        index = 0; // no separator in the name
+    } else {
+        ++index; // skip past the separator
+    }
+    
+    string::size_type firstDot = path.find(".", index);
+    if ((firstDot != string::npos)  && (path.find(sgDirPathSep, firstDot) == string::npos)) {
+        return boost::to_lower_copy(path.substr(firstDot + 1));
+    } else {
+        return "";
     }
 }
 
 void SGPath::validate() const
 {
-  if (_cached) {
+  if (_cached && _cacheEnabled) {
     return;
   }
   
@@ -221,6 +280,7 @@
     _exists = true;
     _isFile = ((S_IFREG & buf.st_mode ) !=0);
     _isDir = ((S_IFDIR & buf.st_mode ) !=0);
+    _modTime = buf.st_mtime;
   }
 
 #else
@@ -232,6 +292,7 @@
     _exists = true;
     _isFile = ((S_ISREG(buf.st_mode )) != 0);
     _isDir = ((S_ISDIR(buf.st_mode )) != 0);
+    _modTime = buf.st_mtime;
   }
   
 #endif
@@ -383,3 +444,60 @@
     return str();
 #endif
 }
+
+bool SGPath::remove()
+{
+    int err = ::unlink(c_str());
+    if (err) {
+        SG_LOG(SG_IO, SG_WARN,  "file remove failed: (" << str() << ") " << strerror(errno));
+    }
+    return (err == 0);
+}
+
+time_t SGPath::modTime() const
+{
+    validate();
+    return _modTime;
+}
+
+bool SGPath::operator==(const SGPath& other) const
+{
+    return (path == other.path);
+}
+
+bool SGPath::operator!=(const SGPath& other) const
+{
+    return (path != other.path);
+}
+
+bool SGPath::rename(const SGPath& newName)
+{
+    if (::rename(c_str(), newName.c_str()) != 0) {
+        SG_LOG(SG_IO, SG_WARN, "renamed failed: from " << str() << " to " << newName.str()
+            << " reason: " << strerror(errno));
+        return false;
+    }
+    
+    path = newName.path;
+    _cached = false;
+    return true;
+}
+
+std::string SGPath::realpath() const
+{
+#ifdef _WIN32
+    // Not implemented for Windows yet. Return original path instead.
+    return path;
+#else
+    char* buf = ::realpath(path.c_str(), NULL);
+    if (!buf)
+    {
+        SG_LOG(SG_IO, SG_ALERT, "ERROR: The path '" << path << "' does not exist in the file system.");
+        return path;
+    }
+    std::string p(buf);
+    free(buf);
+    return p;
+#endif
+}
+

Modified: simgear/trunk/simgear/misc/sg_path.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/sg_path.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/sg_path.hxx (original)
+++ simgear/trunk/simgear/misc/sg_path.hxx Sun Jul 15 09:07:01 2012
@@ -32,6 +32,7 @@
 
 #include <simgear/compiler.h>
 #include <string>
+#include <ctime>
 
 #include <simgear/math/sg_types.hxx>
 
@@ -49,10 +50,6 @@
 
 class SGPath {
 
-private:
-
-    std::string path;
-
 public:
 
     /** Default constructor */
@@ -86,6 +83,15 @@
     void set( const std::string& p );
     SGPath& operator= ( const char* p ) { this->set(p); return *this; }
 
+    bool operator==(const SGPath& other) const;
+    bool operator!=(const SGPath& other) const;
+    
+    /**
+     * Set if file information (exists, type, mod-time) is cached or
+     * retrieved each time it is queried. Caching is enabled by default
+     */
+    void set_cached(bool cached);
+    
     /**
      * Append another piece to the existing path.  Inserts a path
      * separator between the existing component and the new component.
@@ -106,6 +112,12 @@
     void concat( const std::string& p );
 
     /**
+     * Returns a string with the absolute pathname that names the same file, whose
+     * resolution does not involve '.', '..', or symbolic links.
+     */
+    std::string realpath() const;
+
+    /**
      * Get the file part of the path (everything after the last path sep)
      * @return file string
      */
@@ -118,17 +130,38 @@
     std::string dir() const;
   
     /**
-     * Get the base part of the path (everything but the extension.)
+     * Get the base part of the path (everything but the final extension.)
      * @return the base string
      */
     std::string base() const;
+
+    /**
+     * Get the base part of the filename (everything before the first '.')
+     * @return the base filename
+     */
+    std::string file_base() const;
 
     /**
      * Get the extension part of the path (everything after the final ".")
      * @return the extension string
      */
     std::string extension() const;
-
+    
+    /**
+     * Get the extension part of the path (everything after the final ".")
+     * converted to lowercase
+     * @return the extension string
+     */
+    std::string lower_extension() const;
+    
+    /**
+     * Get the complete extension part of the path (everything after the first ".")
+     * this might look like 'tar.gz' or 'txt.Z', or might be identical to 'extension' above
+     * the extension is converted to lowercase.
+     * @return the extension string
+     */
+    std::string complete_lower_extension() const;
+    
     /**
      * Get the path string
      * @return path string
@@ -176,18 +209,46 @@
      * check for default constructed path
      */
     bool isNull() const;
+    
+    /**
+     * delete the file, if possible
+     */
+    bool remove();
+    
+    /**
+     * modification time of the file
+     */
+    time_t modTime() const;
+    
+    /**
+     * rename the file / directory we point at, to a new name
+     * this may fail if the new location is on a different volume / share,
+     * or if the destination already exists, or is not writeable
+     */
+    bool rename(const SGPath& newName);
 private:
 
     void fix();
 
     void validate() const;
 
-    mutable bool _cached;
-    mutable bool _exists;
-    mutable bool _isDir;
-    mutable bool _isFile;
+    std::string path;
+    
+    mutable bool _cached : 1;
+    bool _cacheEnabled : 1; ///< cacheing can be disbled if required
+    mutable bool _exists : 1;
+    mutable bool _isDir : 1;
+    mutable bool _isFile : 1;
+    mutable time_t _modTime;
 };
 
+/// 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 SGPath& p)
+{ return s << "Path \"" << p.str() << "\""; }
+
 
 /**
  * Split a directory string into a list of it's parent directories.

Modified: simgear/trunk/simgear/misc/strutils.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/strutils.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/strutils.cxx (original)
+++ simgear/trunk/simgear/misc/strutils.cxx Sun Jul 15 09:07:01 2012
@@ -22,11 +22,13 @@
 
 #include <ctype.h>
 #include <cstring>
+#include <sstream>
 
 #include "strutils.hxx"
 
 using std::string;
 using std::vector;
+using std::stringstream;
 
 namespace simgear {
     namespace strutils {
@@ -213,5 +215,83 @@
 		return (n != string::npos) && (n == s.length() - substr.length());
 	}
 
+    string simplify(const string& s)
+    {
+        string result; // reserve size of 's'?
+        string::const_iterator it = s.begin(),
+            end = s.end();
+    
+    // advance to first non-space char - simplifes logic in main loop,
+    // since we can always prepend a single space when we see a 
+    // space -> non-space transition
+        for (; (it != end) && isspace(*it); ++it) { /* nothing */ }
+        
+        bool lastWasSpace = false;
+        for (; it != end; ++it) {
+            char c = *it;
+            if (isspace(c)) {
+                lastWasSpace = true;
+                continue;
+            }
+            
+            if (lastWasSpace) {
+                result.push_back(' ');
+            }
+            
+            lastWasSpace = false;
+            result.push_back(c);
+        }
+        
+        return result;
+    }
+    
+    int to_int(const std::string& s, int base)
+    {
+        stringstream ss(s);
+        switch (base) {
+        case 8:      ss >> std::oct; break;
+        case 16:     ss >> std::hex; break;
+        default: break;
+        }
+        
+        int result;
+        ss >> result;
+        return result;
+    }
+    
+    int compare_versions(const string& v1, const string& v2)
+    {
+        vector<string> v1parts(split(v1, "."));
+        vector<string> v2parts(split(v2, "."));
+
+        int lastPart = std::min(v1parts.size(), v2parts.size());
+        for (int part=0; part < lastPart; ++part) {
+            int part1 = to_int(v1parts[part]);
+            int part2 = to_int(v2parts[part]);
+
+            if (part1 != part2) {
+                return part1 - part2;
+            }
+        } // of parts iteration
+
+        // reached end - longer wins
+        return v1parts.size() - v2parts.size();
+    }
+    
+    string join(const string_list& l, const string& joinWith)
+    {
+        string result;
+        unsigned int count = l.size();
+        for (unsigned int i=0; i < count; ++i) {
+            result += l[i];
+            if (i < (count - 1)) {
+                result += joinWith;
+            }
+        }
+        
+        return result;
+    }
+    
     } // end namespace strutils
+    
 } // end namespace simgear

Modified: simgear/trunk/simgear/misc/strutils.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/strutils.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/strutils.hxx (original)
+++ simgear/trunk/simgear/misc/strutils.hxx Sun Jul 15 09:07:01 2012
@@ -33,6 +33,7 @@
 #include <vector>
 #include <cstdlib>
 
+typedef std::vector < std::string > string_list;
 
 namespace simgear {
   namespace strutils {
@@ -93,10 +94,16 @@
 	 * resulting in at most maxsplit+1 words.
 	 * @return Array of words.
 	 */
-	std::vector<std::string>
+	string_list
 	split( const std::string& s,
 	       const char* sep = 0,
 	       int maxsplit = 0 );
+
+       /**
+        * create a single string by joining the elements of a list with
+        * another string.
+        */
+       std::string join(const string_list& l, const std::string& joinWith = "");
 
 	/**
 	 * Test if a string starts with a string 
@@ -116,6 +123,25 @@
 	 */
 	bool ends_with( const std::string & s, const std::string & substr );
   
+    /**
+     * Strip all leading/trailing whitespace, and transform all interal
+     * whitespace into a single ' ' character - i.e newlines/carriage returns/
+     * tabs/multiple spaces will be condensed.
+     */
+    std::string simplify(const std::string& s);
+    
+    /**
+     * convert a string representing a decimal number, to an int
+     */
+    int to_int(const std::string& s, int base = 10);
+    
+    /**
+     * Like strcmp(), but for dotted versions strings NN.NN.NN
+     * any number of terms are support.
+     * @return 0 if versions match, -ve number if v1 is lower, +ve if v1
+     * is greater
+     */
+    int compare_versions(const std::string& v1, const std::string& v2);
   } // end namespace strutils
 } // end namespace simgear
 

Modified: simgear/trunk/simgear/misc/texcoord.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/texcoord.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/texcoord.cxx (original)
+++ simgear/trunk/simgear/misc/texcoord.cxx Sun Jul 15 09:07:01 2012
@@ -213,7 +213,8 @@
     // cout << "degree_height = " << degree_height << endl;
 
     // find min/max of fan
-    SGVec2f tmin, tmax;
+    SGVec2f tmin(0.0, 0.0);
+    SGVec2f tmax(0.0, 0.0);
     bool first = true;
 
     int i;

Modified: simgear/trunk/simgear/misc/zfstream.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/zfstream.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/zfstream.cxx (original)
+++ simgear/trunk/simgear/misc/zfstream.cxx Sun Jul 15 09:07:01 2012
@@ -167,7 +167,7 @@
 
 
 std::streampos
-gzfilebuf::seekoff( std::streamoff, ios_seekdir, int )
+gzfilebuf::seekoff( std::streamoff, ios_seekdir, ios_openmode )
 {
     return std::streampos(EOF);
 }

Modified: simgear/trunk/simgear/misc/zfstream.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/misc/zfstream.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/misc/zfstream.hxx (original)
+++ simgear/trunk/simgear/misc/zfstream.hxx Sun Jul 15 09:07:01 2012
@@ -90,7 +90,7 @@
     bool is_open() const { return (file != NULL); }
 
     /** @return stream position */
-    virtual std::streampos seekoff( std::streamoff off, ios_seekdir way, int which );
+    virtual std::streampos seekoff( std::streamoff off, ios_seekdir way, ios_openmode which );
 
     /** sync the stream */
     virtual int sync();

Modified: simgear/trunk/simgear/nasal/code.c
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/nasal/code.c?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/nasal/code.c (original)
+++ simgear/trunk/simgear/nasal/code.c Sun Jul 15 09:07:01 2012
@@ -269,7 +269,7 @@
     args += c->nOptArgs;
     if(c->needArgVector || nargs > 0) {
         naRef argv = naNewVector(ctx);
-        naVec_setsize(argv, nargs > 0 ? nargs : 0);
+        naVec_setsize(ctx, argv, nargs > 0 ? nargs : 0);
         for(i=0; i<nargs; i++)
             PTR(argv).vec->rec->array[i] = *args++;
         naiHash_newsym(PTR(f->locals).hash, &c->constants[c->restArgSym], &argv);
@@ -349,7 +349,7 @@
     if(IS_VEC(l) && IS_VEC(r)) {
         int i, ls = naVec_size(l), rs = naVec_size(r);
         naRef v = naNewVector(ctx);
-        naVec_setsize(v, ls + rs);
+        naVec_setsize(ctx, v, ls + rs);
         for(i=0; i<ls; i+=1) naVec_set(v, i, naVec_get(l, i));
         for(i=0; i<rs; i+=1) naVec_set(v, i+ls, naVec_get(r, i));
         return v;

Modified: simgear/trunk/simgear/nasal/codegen.c
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/nasal/codegen.c?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/nasal/codegen.c (original)
+++ simgear/trunk/simgear/nasal/codegen.c Sun Jul 15 09:07:01 2012
@@ -536,6 +536,9 @@
 {
     struct Token *lv = LEFT(t), *rv = RIGHT(t);
     int len, dummy, var=0;
+    if (!lv)
+        naParseError(p, "bad assignment, missing variable", t->line);
+    else
     if(parListLen(lv) || (lv->type == TOK_VAR && parListLen(RIGHT(lv)))) {
         if(lv->type == TOK_VAR) { lv = RIGHT(lv); var = 1; }
         len = parListLen(lv);

Modified: simgear/trunk/simgear/nasal/iolib.c
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/nasal/iolib.c?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/nasal/iolib.c (original)
+++ simgear/trunk/simgear/nasal/iolib.c Sun Jul 15 09:07:01 2012
@@ -228,7 +228,7 @@
         naRuntimeError(ctx, strerror(errno));
     }
     result = naNewVector(ctx);
-    naVec_setsize(result, 12);
+    naVec_setsize(ctx, result, 12);
 #define FLD(x) naVec_set(result, n++, naNum(s.st_##x));
     FLD(dev);  FLD(ino);  FLD(mode);  FLD(nlink);  FLD(uid);  FLD(gid);
     FLD(rdev); FLD(size); FLD(atime); FLD(mtime);  FLD(ctime);

Modified: simgear/trunk/simgear/nasal/lib.c
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/nasal/lib.c?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/nasal/lib.c (original)
+++ simgear/trunk/simgear/nasal/lib.c Sun Jul 15 09:07:01 2012
@@ -56,7 +56,7 @@
 static naRef f_setsize(naContext c, naRef me, int argc, naRef* args)
 {
     if(argc < 2 || !naIsVector(args[0])) ARGERR();
-    naVec_setsize(args[0], (int)naNumValue(args[1]).num);
+    naVec_setsize(c, args[0], (int)naNumValue(args[1]).num);
     return args[0];
 }
 
@@ -74,7 +74,7 @@
     if(naIsNil(nlen) || len > naVec_size(v) - start)
         len = naVec_size(v) - start;
     result = naNewVector(c);
-    naVec_setsize(result, len);
+    naVec_setsize(c, result, len);
     for(i=0; i<len; i++)
         naVec_set(result, i, naVec_get(v, start + i));
     return result;
@@ -533,7 +533,7 @@
     qsort(sd.recs, sd.n, sizeof(sd.recs[0]),
           (int(*)(const void*,const void*))sortcmp);
     out = naNewVector(c);
-    naVec_setsize(out, sd.n);
+    naVec_setsize(c, out, sd.n);
     for(i=0; i<sd.n; i++)
         PTR(out).vec->rec->array[i] = sd.elems[sd.recs[i].i];
     naFree(sd.recs);

Modified: simgear/trunk/simgear/nasal/nasal.h
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/nasal/nasal.h?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/nasal/nasal.h (original)
+++ simgear/trunk/simgear/nasal/nasal.h Sun Jul 15 09:07:01 2012
@@ -166,7 +166,7 @@
 void naVec_set(naRef vec, int i, naRef o);
 int naVec_append(naRef vec, naRef o);
 naRef naVec_removelast(naRef vec);
-void naVec_setsize(naRef vec, int sz);
+void naVec_setsize(naContext c, naRef vec, int sz);
 
 // Hash utilities:
 int naHash_size(naRef h);

Modified: simgear/trunk/simgear/nasal/vector.c
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/nasal/vector.c?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/nasal/vector.c (original)
+++ simgear/trunk/simgear/nasal/vector.c Sun Jul 15 09:07:01 2012
@@ -69,16 +69,21 @@
     return 0;
 }
 
-void naVec_setsize(naRef vec, int sz)
+void naVec_setsize(naContext c, naRef vec, int sz)
 {
-    int i;
-    struct VecRec* v = PTR(vec).vec->rec;
-    struct VecRec* nv = naAlloc(sizeof(struct VecRec) + sizeof(naRef) * sz);
-    nv->size = sz;
-    nv->alloced = sz;
-    for(i=0; i<sz; i++)
-        nv->array[i] = (v && i < v->size) ? v->array[i] : naNil();
-    naGC_swapfree((void*)&(PTR(vec).vec->rec), nv);
+    if (sz < 0)
+        naRuntimeError(c, "size cannot be negative");
+    else
+    {
+        int i;
+        struct VecRec* v = PTR(vec).vec->rec;
+        struct VecRec* nv = naAlloc(sizeof(struct VecRec) + sizeof(naRef) * sz);
+        nv->size = sz;
+        nv->alloced = sz;
+        for(i=0; i<sz; i++)
+            nv->array[i] = (v && i < v->size) ? v->array[i] : naNil();
+        naGC_swapfree((void*)&(PTR(vec).vec->rec), nv);
+    }
 }
 
 naRef naVec_removelast(naRef vec)

Modified: simgear/trunk/simgear/props/condition.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/condition.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/condition.cxx (original)
+++ simgear/trunk/simgear/props/condition.cxx Sun Jul 15 09:07:01 2012
@@ -126,21 +126,27 @@
                                 const char * propname );
   virtual void setRightProperty( SGPropertyNode *prop_root,
                                  const char * propname );
+  virtual void setPrecisionProperty( SGPropertyNode *prop_root,
+                                 const char * propname );
   // will make a local copy
   virtual void setLeftValue (const SGPropertyNode * value);
   virtual void setRightValue (const SGPropertyNode * value);
+  virtual void setPrecisionValue (const SGPropertyNode * value);
   
   void setLeftDExpression(SGExpressiond* dexp);
   void setRightDExpression(SGExpressiond* dexp);
+  void setPrecisionDExpression(SGExpressiond* dexp);
   
 private:
   Type _type;
   bool _reverse;
   SGPropertyNode_ptr _left_property;
   SGPropertyNode_ptr _right_property;
+  SGPropertyNode_ptr _precision_property;
   
   SGSharedPtr<SGExpressiond> _left_dexp;
   SGSharedPtr<SGExpressiond> _right_dexp;
+  SGSharedPtr<SGExpressiond> _precision_dexp;
 };
 
 
@@ -261,8 +267,20 @@
 // Implementation of SGComparisonCondition.
 ////////////////////////////////////////////////////////////////////////
 
+template<typename T> 
+static int doComp( T v1, T v2, T e )
+{
+  T d = v1 - v2;
+  if( d < -e )
+    return SGComparisonCondition::LESS_THAN;
+  else if( d > e )
+    return SGComparisonCondition::GREATER_THAN;
+  else
+    return SGComparisonCondition::EQUALS;
+}
+
 static int
-doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
+doComparison (const SGPropertyNode * left, const SGPropertyNode * right, const SGPropertyNode * precision )
 {
   using namespace simgear;
   switch (left->getType()) {
@@ -277,9 +295,28 @@
       return SGComparisonCondition::EQUALS;
     break;
   }
-  case props::INT: {
-    int v1 = left->getIntValue();
-    int v2 = right->getIntValue();
+  case props::INT:
+    return doComp<int>(left->getIntValue(), right->getIntValue(), 
+           precision ? abs(precision->getIntValue()/2) : 0 );
+
+  case props::LONG:
+    return doComp<long>(left->getLongValue(), right->getLongValue(), 
+           precision ? abs(precision->getLongValue()/2L) : 0L );
+
+  case props::FLOAT:
+    return doComp<float>(left->getFloatValue(), right->getFloatValue(), 
+           precision ? fabs(precision->getFloatValue()/2.0f) : 0.0f );
+
+  case props::DOUBLE:
+    return doComp<double>(left->getDoubleValue(), right->getDoubleValue(), 
+           precision ? fabs(precision->getDoubleValue()/2.0) : 0.0 );
+
+  case props::STRING:
+  case props::NONE:
+  case props::UNSPECIFIED: {
+    size_t l = precision ? precision->getLongValue() : string::npos;
+    string v1 = string(left->getStringValue()).substr(0,l);
+    string v2 = string(right->getStringValue()).substr(0,l);
     if (v1 < v2)
       return SGComparisonCondition::LESS_THAN;
     else if (v1 > v2)
@@ -288,52 +325,6 @@
       return SGComparisonCondition::EQUALS;
     break;
   }
-  case props::LONG: {
-    long v1 = left->getLongValue();
-    long v2 = right->getLongValue();
-    if (v1 < v2)
-      return SGComparisonCondition::LESS_THAN;
-    else if (v1 > v2)
-      return SGComparisonCondition::GREATER_THAN;
-    else
-      return SGComparisonCondition::EQUALS;
-    break;
-  }
-  case props::FLOAT: {
-    float v1 = left->getFloatValue();
-    float v2 = right->getFloatValue();
-    if (v1 < v2)
-      return SGComparisonCondition::LESS_THAN;
-    else if (v1 > v2)
-      return SGComparisonCondition::GREATER_THAN;
-    else
-      return SGComparisonCondition::EQUALS;
-    break;
-  }
-  case props::DOUBLE: {
-    double v1 = left->getDoubleValue();
-    double v2 = right->getDoubleValue();
-    if (v1 < v2)
-      return SGComparisonCondition::LESS_THAN;
-    else if (v1 > v2)
-      return SGComparisonCondition::GREATER_THAN;
-    else
-      return SGComparisonCondition::EQUALS;
-    break;
-  }
-  case props::STRING:
-  case props::NONE:
-  case props::UNSPECIFIED: {
-    string v1 = left->getStringValue();
-    string v2 = right->getStringValue();
-    if (v1 < v2)
-      return SGComparisonCondition::LESS_THAN;
-    else if (v1 > v2)
-      return SGComparisonCondition::GREATER_THAN;
-    else
-      return SGComparisonCondition::EQUALS;
-    break;
-  }
   default:
     throw sg_exception("condition: unrecognized node type in comparison");
   }
@@ -367,8 +358,12 @@
   if (_right_dexp) {
     _right_property->setDoubleValue(_right_dexp->getValue(NULL));
   }
+
+  if (_precision_dexp) {
+    _precision_property->setDoubleValue(_precision_dexp->getValue(NULL));
+  }
         
-  int cmp = doComparison(_left_property, _right_property);
+  int cmp = doComparison(_left_property, _right_property, _precision_property );
   if (!_reverse)
     return (cmp == _type);
   else
@@ -390,11 +385,23 @@
 }
 
 void
+SGComparisonCondition::setPrecisionProperty( SGPropertyNode *prop_root,
+                                         const char * propname )
+{
+  _precision_property = prop_root->getNode(propname, true);
+}
+
+void
 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
 {
   _left_property = new SGPropertyNode(*node);
 }
 
+void
+SGComparisonCondition::setPrecisionValue (const SGPropertyNode *node)
+{
+  _precision_property = new SGPropertyNode(*node);
+}
 
 void
 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
@@ -414,6 +421,13 @@
 {
   _right_property = new SGPropertyNode();
   _right_dexp = dexp;
+}
+
+void
+SGComparisonCondition::setPrecisionDExpression(SGExpressiond* dexp)
+{
+  _precision_property = new SGPropertyNode();
+  _precision_dexp = dexp;
 }
 ////////////////////////////////////////////////////////////////////////
 // Read a condition and use it if necessary.
@@ -479,34 +493,54 @@
 		bool reverse)
 {
   SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
-  if (node->nChildren() != 2) {
-    throw sg_exception("condition: comparison without two children");
+  if (node->nChildren() < 2 || node->nChildren() > 3 ) {
+    throw sg_exception("condition: comparison without two or three children");
   }
   
   const SGPropertyNode* left = node->getChild(0), 
     *right = node->getChild(1);
-  string leftName(left->getName());
-  if (leftName == "property") {
-    condition->setLeftProperty(prop_root, left->getStringValue());
-  } else if (leftName == "value") {
-    condition->setLeftValue(left);
-  } else if (leftName == "expression") {
-    SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
-    condition->setLeftDExpression(exp);
-  } else {
-    throw sg_exception("Unknown condition comparison left child:" + leftName);
+
+  {
+    string leftName(left->getName());
+    if (leftName == "property") {
+      condition->setLeftProperty(prop_root, left->getStringValue());
+    } else if (leftName == "value") {
+      condition->setLeftValue(left);
+    } else if (leftName == "expression") {
+      SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
+      condition->setLeftDExpression(exp);
+    } else {
+      throw sg_exception("Unknown condition comparison left child:" + leftName);
+    }
   }
     
-  string rightName(right->getName());
-  if (rightName == "property") {
-    condition->setRightProperty(prop_root, right->getStringValue());
-  } else if (rightName == "value") {
-    condition->setRightValue(right);
-  } else if (rightName == "expression") {
-    SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
-    condition->setRightDExpression(exp);
-  } else {
-    throw sg_exception("Unknown condition comparison right child:" + rightName);
+  {
+    string rightName(right->getName());
+    if (rightName == "property") {
+      condition->setRightProperty(prop_root, right->getStringValue());
+    } else if (rightName == "value") {
+      condition->setRightValue(right);
+    } else if (rightName == "expression") {
+      SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
+      condition->setRightDExpression(exp);
+    } else {
+      throw sg_exception("Unknown condition comparison right child:" + rightName);
+    }
+  }
+  
+  if( node->nChildren() == 3 ) {
+    const SGPropertyNode *n = node->getChild(2);
+    string name(n->getName());
+    if (name == "precision-property") {
+      condition->setPrecisionProperty(prop_root, n->getStringValue());
+    } else if (name == "precision-value") {
+      condition->setPrecisionValue(n);
+    } else if (name == "precision-expression") {
+      SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
+      condition->setPrecisionDExpression(exp);
+    } else {
+      throw sg_exception("Unknown condition comparison precision child:" + name );
+    }
   }
   
   return condition;

Modified: simgear/trunk/simgear/props/condition.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/condition.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/condition.hxx (original)
+++ simgear/trunk/simgear/props/condition.hxx Sun Jul 15 09:07:01 2012
@@ -10,11 +10,11 @@
 #ifndef __SG_CONDITION_HXX
 #define __SG_CONDITION_HXX
 
-#include <simgear/debug/logstream.hxx>
-#include <simgear/props/props.hxx>
-#include <simgear/props/props_io.hxx>
 #include <simgear/structure/SGReferenced.hxx>
-
+#include <simgear/structure/SGSharedPtr.hxx>
+
+class SGPropertyNode;
+
 ////////////////////////////////////////////////////////////////////////
 // Conditions.
 ////////////////////////////////////////////////////////////////////////

Modified: simgear/trunk/simgear/props/propertyObject.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/propertyObject.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/propertyObject.cxx (original)
+++ simgear/trunk/simgear/props/propertyObject.cxx Sun Jul 15 09:07:01 2012
@@ -33,6 +33,13 @@
 void PropertyObjectBase::setDefaultRoot(SGPropertyNode* aRoot)
 {
   static_defaultRoot = aRoot;
+}
+  
+PropertyObjectBase::PropertyObjectBase() :
+  _path(NULL),
+  _prop(NULL)
+{
+    
 }
 
 PropertyObjectBase::PropertyObjectBase(const PropertyObjectBase& aOther) :

Modified: simgear/trunk/simgear/props/propertyObject.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/propertyObject.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/propertyObject.hxx (original)
+++ simgear/trunk/simgear/props/propertyObject.hxx Sun Jul 15 09:07:01 2012
@@ -28,6 +28,8 @@
 public:
   static void setDefaultRoot(SGPropertyNode* aRoot);
   
+  PropertyObjectBase();
+  
   PropertyObjectBase(const PropertyObjectBase& aOther);
     
   PropertyObjectBase(const char* aChild);
@@ -57,6 +59,8 @@
 class PropertyObject : PropertyObjectBase
 {
 public:
+  PropertyObject();
+  
   /**
    * Create from path relative to the default root, and option default value
    */
@@ -220,11 +224,9 @@
 
 } // of namespace simgear
 
-/*
 typedef simgear::PropertyObject<double> SGPropObjDouble;
 typedef simgear::PropertyObject<bool> SGPropObjBool;
 typedef simgear::PropertyObject<std::string> SGPropObjString;
 typedef simgear::PropertyObject<long> SGPropObjInt;
-*/
 
 #endif

Modified: simgear/trunk/simgear/props/propertyObject_test.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/propertyObject_test.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/propertyObject_test.cxx (original)
+++ simgear/trunk/simgear/props/propertyObject_test.cxx Sun Jul 15 09:07:01 2012
@@ -1,9 +1,21 @@
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
+#ifdef NDEBUG
+// Always enable DEBUG mode in test application, otherwise "assert" test
+// statements have no effect and don't actually test anything (catch 17 ;-) ).
+#undef NDEBUG
+#endif
 
 #include <simgear/compiler.h>
 
 #include <iostream>
 #include <cassert>
 #include <cstring>
+
+// working around MSVC weirdness with props.hxx and SGMathFwd
+#include <simgear/math/SGMath.hxx>
 
 #include "propertyObject.hxx"
 
@@ -37,9 +49,11 @@
 
   double ff(aFoo);
   assert(ff == 12.0); // comparison with literal
+  if (ff != 12.0) cout << "Error: a/foo != 12!" << endl;
   
   const float fff(12.0f);
   assert(fff == aFoo); // comparion with float value
+  if (fff != aFoo) cout << "Error: 12 != a/foo" << endl;
 
   return true;
 }
@@ -135,8 +149,9 @@
   PropertyObject<bool> b("not/found/honest");
 
   try {
-    bool v = b;    
+    bool v = b;
     assert(false && "read of missing property didn't throw");
+    (void) v; // don't warn about unused variable
   } catch (sg_exception& e) {
     // expected
   }

Modified: simgear/trunk/simgear/props/props.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/props.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/props.cxx (original)
+++ simgear/trunk/simgear/props/props.cxx Sun Jul 15 09:07:01 2012
@@ -664,7 +664,8 @@
  * Copy constructor.
  */
 SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
-  : _index(node._index),
+  : SGReferenced(node),
+    _index(node._index),
     _name(node._name),
     _parent(0),			// don't copy the parent
     _type(node._type),

Modified: simgear/trunk/simgear/props/props.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/props.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/props.hxx (original)
+++ simgear/trunk/simgear/props/props.hxx Sun Jul 15 09:07:01 2012
@@ -1938,6 +1938,36 @@
 };
 }
 }
+
+/** Convenience class for change listener callbacks without
+ * creating a derived class implementing a "valueChanged" method.
+ * Also removes listener on destruction automatically.
+ */
+template<class T>
+class SGPropertyChangeCallback
+    : public SGPropertyChangeListener
+{
+public:
+    SGPropertyChangeCallback(T* obj, void (T::*method)(SGPropertyNode*),
+                             SGPropertyNode_ptr property,bool initial=false)
+        : _obj(obj), _callback(method), _property(property)
+    {
+        _property->addChangeListener(this,initial);
+    }
+    virtual ~SGPropertyChangeCallback()
+    {
+        _property->removeChangeListener(this);
+    }
+    void valueChanged (SGPropertyNode * node)
+    {
+        (_obj->*_callback)(node);
+    }
+private:
+    T* _obj;
+    void (T::*_callback)(SGPropertyNode*);
+    SGPropertyNode_ptr _property;
+};
+
 #endif // __PROPS_HXX
 
 // end of props.hxx

Modified: simgear/trunk/simgear/props/props_io.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/props_io.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/props_io.cxx (original)
+++ simgear/trunk/simgear/props/props_io.cxx Sun Jul 15 09:07:01 2012
@@ -21,6 +21,7 @@
 #include <simgear/math/SGMath.hxx>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/xml/easyxml.hxx>
+#include <simgear/misc/ResourceManager.hxx>
 
 #include "props.hxx"
 #include "props_io.hxx"
@@ -170,12 +171,15 @@
 				// Check for an include.
     attval = atts.getValue("include");
     if (attval != 0) {
-      SGPath path(SGPath(_base).dir());
-      path.append(attval);
       try {
-	readProperties(path.str(), _root, 0, _extended);
+          SGPath path = simgear::ResourceManager::instance()->findPath(attval, SGPath(_base).dir());
+          if (path.isNull())
+          {
+              throw sg_io_exception("Cannot open file", sg_location(attval));
+          }
+          readProperties(path.str(), _root, 0, _extended);
       } catch (sg_io_exception &e) {
-	setException(e);
+          setException(e);
       }
     }
 
@@ -242,12 +246,15 @@
     bool omit = false;
     attval = atts.getValue("include");
     if (attval != 0) {
-      SGPath path(SGPath(_base).dir());
-      path.append(attval);
       try {
-	readProperties(path.str(), node, 0, _extended);
+          SGPath path = simgear::ResourceManager::instance()->findPath(attval, SGPath(_base).dir());
+          if (path.isNull())
+          {
+              throw sg_io_exception("Cannot open file", sg_location(attval));
+          }
+          readProperties(path.str(), node, 0, _extended);
       } catch (sg_io_exception &e) {
-	setException(e);
+          setException(e);
       }
 
       attval = atts.getValue("omit-node");

Modified: simgear/trunk/simgear/props/props_io.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/props_io.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/props_io.hxx (original)
+++ simgear/trunk/simgear/props/props_io.hxx Sun Jul 15 09:07:01 2012
@@ -15,11 +15,7 @@
 #include <simgear/compiler.h>
 #include <simgear/props/props.hxx>
 
-#include <stdio.h>
-
 #include <string>
-#include <vector>
-#include <map>
 #include <iosfwd>
 
 /**

Modified: simgear/trunk/simgear/props/props_test.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/props_test.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/props_test.cxx (original)
+++ simgear/trunk/simgear/props/props_test.cxx Sun Jul 15 09:07:01 2012
@@ -3,9 +3,17 @@
 // Test harness.
 ////////////////////////////////////////////////////////////////////////
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
 #include <simgear/compiler.h>
 
 #include <iostream>
+
+// working around MSVC weirdness with props.hxx and SGMathFwd
+#include <simgear/math/SGMath.hxx>
+
 #include "props.hxx"
 #include "props_io.hxx"
 

Modified: simgear/trunk/simgear/props/tiedpropertylist.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/props/tiedpropertylist.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/props/tiedpropertylist.hxx (original)
+++ simgear/trunk/simgear/props/tiedpropertylist.hxx Sun Jul 15 09:07:01 2012
@@ -51,7 +51,7 @@
     template<typename T> SGPropertyNode_ptr Tie( SGPropertyNode_ptr node, const SGRawValue<T> &rawValue, bool useDefault = true  ) {
         bool success = node->tie( rawValue, useDefault );
         if( success ) {
-            SG_LOG( SG_ALL, SG_INFO, "Tied " << node->getPath() );
+            SG_LOG( SG_ALL, SG_DEBUG, "Tied " << node->getPath() );
             push_back( node );
         } else {
 #if PROPS_STANDALONE
@@ -125,7 +125,7 @@
 
     void Untie() {
         while( size() > 0 ) {
-            SG_LOG( SG_ALL, SG_INFO, "untie of " << back()->getPath() );
+            SG_LOG( SG_ALL, SG_DEBUG, "untie of " << back()->getPath() );
             back()->untie();
             pop_back();
         }

Modified: simgear/trunk/simgear/scene/material/Effect.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/Effect.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/Effect.cxx (original)
+++ simgear/trunk/simgear/scene/material/Effect.cxx Sun Jul 15 09:07:01 2012
@@ -46,6 +46,7 @@
 #include <osg/Material>
 #include <osg/Math>
 #include <osg/PolygonMode>
+#include <osg/PolygonOffset>
 #include <osg/Program>
 #include <osg/Referenced>
 #include <osg/RenderInfo>
@@ -66,7 +67,7 @@
 #include <osgDB/ReadFile>
 #include <osgDB/Registry>
 
-#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/scene/tgdb/userdata.hxx>
 #include <simgear/scene/util/SGSceneFeatures.hxx>
 #include <simgear/scene/util/StateAttributeFactory.hxx>
@@ -89,7 +90,7 @@
 }
 
 Effect::Effect(const Effect& rhs, const CopyOp& copyop)
-    : root(rhs.root), parametersProp(rhs.parametersProp), _cache(0),
+    : osg::Object(rhs,copyop), root(rhs.root), parametersProp(rhs.parametersProp), _cache(0),
       _isRealized(rhs._isRealized)
 {
     typedef vector<ref_ptr<Technique> > TechniqueList;
@@ -153,7 +154,7 @@
 }
 
 void buildPass(Effect* effect, Technique* tniq, const SGPropertyNode* prop,
-               const SGReaderWriterXMLOptions* options)
+               const SGReaderWriterOptions* options)
 {
     Pass* pass = new Pass;
     tniq->passes.push_back(pass);
@@ -202,12 +203,12 @@
 struct LightingBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options);
+                        const SGReaderWriterOptions* options);
 };
 
 void LightingBuilder::buildAttribute(Effect* effect, Pass* pass,
                                      const SGPropertyNode* prop,
-                                     const SGReaderWriterXMLOptions* options)
+                                     const SGReaderWriterOptions* options)
 {
     const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
     if (!realProp)
@@ -221,7 +222,7 @@
 struct ShadeModelBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp)
@@ -243,7 +244,7 @@
 struct CullFaceBuilder : PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp) {
@@ -271,7 +272,7 @@
 struct ColorMaskBuilder : PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp)
@@ -298,7 +299,7 @@
 struct HintBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp)
@@ -314,7 +315,7 @@
 struct RenderBinBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -341,7 +342,7 @@
 struct MaterialBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options);
+                        const SGReaderWriterOptions* options);
 };
 
 EffectNameValue<Material::ColorMode> colorModeInit[] =
@@ -357,7 +358,7 @@
 
 void MaterialBuilder::buildAttribute(Effect* effect, Pass* pass,
                                      const SGPropertyNode* prop,
-                                     const SGReaderWriterXMLOptions* options)
+                                     const SGReaderWriterOptions* options)
 {
     if (!isAttributeActive(effect, prop))
         return;
@@ -427,7 +428,7 @@
 struct BlendBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -540,7 +541,7 @@
 struct StencilBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -618,7 +619,7 @@
 struct AlphaTestBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -735,7 +736,7 @@
 struct ShaderProgramBuilder : PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options);
+                        const SGReaderWriterOptions* options);
 };
 
 
@@ -762,7 +763,7 @@
 
 void ShaderProgramBuilder::buildAttribute(Effect* effect, Pass* pass,
                                           const SGPropertyNode* prop,
-                                          const SGReaderWriterXMLOptions*
+                                          const SGReaderWriterOptions*
                                           options)
 {
     using namespace boost;
@@ -898,7 +899,7 @@
 struct UniformBuilder :public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         if (!texture0.valid()) {
             texture0 = new Uniform(Uniform::SAMPLER_2D, "texture");
@@ -1012,7 +1013,7 @@
 struct NameBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         // name can't use <use>
         string name = prop->getStringValue();
@@ -1034,7 +1035,7 @@
 struct PolygonModeBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -1059,10 +1060,38 @@
 
 InstallAttributeBuilder<PolygonModeBuilder> installPolygonMode("polygon-mode");
 
+struct PolygonOffsetBuilder : public PassAttributeBuilder
+{
+    void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
+                        const SGReaderWriterOptions* options)
+    {
+        if (!isAttributeActive(effect, prop))
+            return;
+        
+        const SGPropertyNode* factor
+           = getEffectPropertyChild(effect, prop, "factor");
+        const SGPropertyNode* units
+           = getEffectPropertyChild(effect, prop, "units");
+        
+        ref_ptr<PolygonOffset> polyoffset = new PolygonOffset;
+        
+        polyoffset->setFactor(factor->getFloatValue());
+        polyoffset->setUnits(units->getFloatValue());
+
+        SG_LOG(SG_INPUT, SG_BULK,
+                   "Set PolygonOffset to " << polyoffset->getFactor() << polyoffset->getUnits() );            
+
+        pass->setAttributeAndModes(polyoffset.get(),
+                                   StateAttribute::OVERRIDE|StateAttribute::ON);
+    }
+};
+
+InstallAttributeBuilder<PolygonOffsetBuilder> installPolygonOffset("polygon-offset");
+
 struct VertexProgramTwoSideBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp)
@@ -1079,7 +1108,7 @@
 struct VertexProgramPointSizeBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         const SGPropertyNode* realProp = getEffectPropertyNode(effect, prop);
         if (!realProp)
@@ -1109,7 +1138,7 @@
 struct DepthBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options)
+                        const SGReaderWriterOptions* options)
     {
         if (!isAttributeActive(effect, prop))
             return;
@@ -1128,7 +1157,7 @@
         const SGPropertyNode* pfar
             = getEffectPropertyChild(effect, prop, "far");
         if (pfar)
-            depth->setZFar(pnear->getValue<double>());
+            depth->setZFar(pfar->getValue<double>());
         const SGPropertyNode* pmask
             = getEffectPropertyChild(effect, prop, "write-mask");
         if (pmask)
@@ -1140,7 +1169,7 @@
 InstallAttributeBuilder<DepthBuilder> installDepth("depth");
 
 void buildTechnique(Effect* effect, const SGPropertyNode* prop,
-                    const SGReaderWriterXMLOptions* options)
+                    const SGReaderWriterOptions* options)
 {
     Technique* tniq = new Technique;
     effect->techniques.push_back(tniq);
@@ -1249,7 +1278,7 @@
 
 // Walk the techniques property tree, building techniques and
 // passes.
-bool Effect::realizeTechniques(const SGReaderWriterXMLOptions* options)
+bool Effect::realizeTechniques(const SGReaderWriterOptions* options)
 {
     if (_isRealized)
         return true;

Modified: simgear/trunk/simgear/scene/material/Effect.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/Effect.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/Effect.hxx (original)
+++ simgear/trunk/simgear/scene/material/Effect.hxx Sun Jul 15 09:07:01 2012
@@ -45,7 +45,7 @@
 {
 class Technique;
 class Effect;
-class SGReaderWriterXMLOptions;
+class SGReaderWriterOptions;
 
 /**
  * Object to be initialized at some point after an effect -- and its
@@ -102,7 +102,7 @@
     /**
      * Build the techniques from the effect properties.
      */
-    bool realizeTechniques(const SGReaderWriterXMLOptions* options = 0);
+    bool realizeTechniques(const SGReaderWriterOptions* options = 0);
     /**
      * Updaters that should be derefed when the effect is
      * deleted. Updaters arrange to be run by listening on properties
@@ -157,7 +157,7 @@
     Cache* _cache;
     friend size_t hash_value(const Key& key);
     friend Effect* makeEffect(SGPropertyNode* prop, bool realizeTechniques,
-                              const SGReaderWriterXMLOptions* options);
+                              const SGReaderWriterOptions* options);
     bool _isRealized;
 };
 // Automatic support for boost hash function
@@ -166,11 +166,11 @@
 
 Effect* makeEffect(const std::string& name,
                    bool realizeTechniques,
-                   const SGReaderWriterXMLOptions* options = 0);
+                   const SGReaderWriterOptions* options = 0);
 
 Effect* makeEffect(SGPropertyNode* prop,
                    bool realizeTechniques,
-                   const SGReaderWriterXMLOptions* options = 0);
+                   const SGReaderWriterOptions* options = 0);
 
 bool makeParametersFromStateSet(SGPropertyNode* paramRoot,
                                 const osg::StateSet* ss);

Modified: simgear/trunk/simgear/scene/material/EffectBuilder.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/EffectBuilder.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/EffectBuilder.cxx (original)
+++ simgear/trunk/simgear/scene/material/EffectBuilder.cxx Sun Jul 15 09:07:01 2012
@@ -2,7 +2,7 @@
 #  include <simgear_config.h>
 #endif
 
-#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/scene/tgdb/userdata.hxx>
 
 #include <simgear/math/SGMath.hxx>
@@ -43,7 +43,7 @@
 }
 
 string getGlobalProperty(const SGPropertyNode* prop,
-                         const SGReaderWriterXMLOptions* options)
+                         const SGReaderWriterOptions* options)
 {
     if (!prop)
         return string();
@@ -54,7 +54,7 @@
     SGPropertyNode_ptr propRoot;
     if (propName[0] == '/') {
         return propName;
-    } else if ((propRoot = options->getPropRoot())) {
+    } else if ((propRoot = options->getPropertyNode())) {
         string result = propRoot->getPath();
         result.append("/");
         result.append(propName);
@@ -102,4 +102,14 @@
 {
 const char* colorFields[] = {"red", "green", "blue", "alpha"};
 }
+  
+PassAttributeBuilder::~PassAttributeBuilder()
+{
 }
+  
+} // of namespace simgear
+
+
+
+
+

Modified: simgear/trunk/simgear/scene/material/EffectBuilder.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/EffectBuilder.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/EffectBuilder.hxx (original)
+++ simgear/trunk/simgear/scene/material/EffectBuilder.hxx Sun Jul 15 09:07:01 2012
@@ -34,7 +34,7 @@
 #include <simgear/math/SGMath.hxx>
 #include <simgear/props/AtomicChangeListener.hxx>
 #include <simgear/props/props.hxx>
-#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/structure/exception.hxx>
 #include <simgear/structure/SGSharedPtr.hxx>
 #include <simgear/structure/Singleton.hxx>
@@ -48,7 +48,7 @@
 {
 class Effect;
 class Pass;
-class SGReaderWriterXMLOptions;
+class SGReaderWriterOptions;
 
 /**
  * Builder that returns an object, probably an OSG object.
@@ -59,10 +59,10 @@
 public:
     virtual ~EffectBuilder() {}
     virtual T* build(Effect* effect, const SGPropertyNode*,
-                     const SGReaderWriterXMLOptions* options) = 0;
+                     const SGReaderWriterOptions* options) = 0;
     static T* buildFromType(Effect* effect, const std::string& type,
                             const SGPropertyNode*props,
-                            const SGReaderWriterXMLOptions* options)
+                            const SGReaderWriterOptions* options)
     {
         BuilderMap& builderMap = getMap();
         typename BuilderMap::iterator iter = builderMap.find(type);
@@ -302,12 +302,12 @@
  * mentioned node name.
  */
 std::string getGlobalProperty(const SGPropertyNode* prop,
-                              const SGReaderWriterXMLOptions *);
+                              const SGReaderWriterOptions *);
 
 template<typename NameItr>
 std::vector<std::string>
 getVectorProperties(const SGPropertyNode* prop,
-                    const SGReaderWriterXMLOptions *options, size_t vecSize,
+                    const SGReaderWriterOptions *options, size_t vecSize,
                     NameItr defaultNames)
 {
     using namespace std;
@@ -318,7 +318,7 @@
     if (useProps.size() == 1) {
         string parentName = useProps[0]->getStringValue();
         if (parentName.size() == 0 || parentName[0] != '/')
-            parentName = options->getPropRoot()->getPath() + "/" + parentName;
+            parentName = options->getPropertyNode()->getPath() + "/" + parentName;
         if (parentName[parentName.size() - 1] != '/')
             parentName.append("/");
         NameItr itr = defaultNames;
@@ -350,11 +350,14 @@
     struct PassAttrMapSingleton : public simgear::Singleton<PassAttrMapSingleton>
     {
         PassAttrMap passAttrMap;
+      
     };
 public:
+    virtual ~PassAttributeBuilder(); // anchor into the compilation unit.
+  
     virtual void buildAttribute(Effect* effect, Pass* pass,
                                 const SGPropertyNode* prop,
-                                const SGReaderWriterXMLOptions* options)
+                                const SGReaderWriterOptions* options)
     = 0;
     static PassAttributeBuilder* find(const std::string& str)
     {
@@ -607,7 +610,7 @@
 template<typename OSGParamType, typename ObjType, typename F>
 void
 initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
-                   const F& setter, const SGReaderWriterXMLOptions* options)
+                   const F& setter, const SGReaderWriterOptions* options)
 {
     const SGPropertyNode* valProp = getEffectPropertyNode(effect, prop);
     if (!valProp)
@@ -628,7 +631,7 @@
 inline void
 initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
                    SetterReturn (ObjType::*setter)(const OSGParamType),
-                   const SGReaderWriterXMLOptions* options)
+                   const SGReaderWriterOptions* options)
 {
     initFromParameters<OSGParamType>(effect, prop, obj,
                                      boost::bind(setter, _1, _2), options);
@@ -658,7 +661,7 @@
 void
 initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
                    const F& setter,
-                   NameItrType nameItr, const SGReaderWriterXMLOptions* options)
+                   NameItrType nameItr, const SGReaderWriterOptions* options)
 {
     typedef typename Bridge<OSGParamType>::sg_type sg_type;
     const int numComponents = props::NumComponents<sg_type>::num_components;
@@ -687,7 +690,7 @@
 inline void
 initFromParameters(Effect* effect, const SGPropertyNode* prop, ObjType* obj,
                    SetterReturn (ObjType::*setter)(const OSGParamType&),
-                   NameItrType nameItr, const SGReaderWriterXMLOptions* options)
+                   NameItrType nameItr, const SGReaderWriterOptions* options)
 {
     initFromParameters<OSGParamType>(effect, prop, obj,
                                      boost::bind(setter, _1, _2), nameItr,

Modified: simgear/trunk/simgear/scene/material/EffectCullVisitor.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/EffectCullVisitor.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/EffectCullVisitor.cxx (original)
+++ simgear/trunk/simgear/scene/material/EffectCullVisitor.cxx Sun Jul 15 09:07:01 2012
@@ -36,6 +36,7 @@
 }
 
 EffectCullVisitor::EffectCullVisitor(const EffectCullVisitor& rhs) :
+    osg::Referenced(rhs),
     CullVisitor(rhs)
 {
 }

Modified: simgear/trunk/simgear/scene/material/Technique.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/Technique.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/Technique.cxx (original)
+++ simgear/trunk/simgear/scene/material/Technique.cxx Sun Jul 15 09:07:01 2012
@@ -58,6 +58,7 @@
 }
 
 Technique::Technique(const Technique& rhs, const osg::CopyOp& copyop) :
+    osg::Object(rhs,copyop),
     _contextMap(rhs._contextMap), _alwaysValid(rhs._alwaysValid),
     _shadowingStateSet(copyop(rhs._shadowingStateSet.get())),
     _validExpression(rhs._validExpression),

Modified: simgear/trunk/simgear/scene/material/Technique.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/Technique.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/Technique.hxx (original)
+++ simgear/trunk/simgear/scene/material/Technique.hxx Sun Jul 15 09:07:01 2012
@@ -103,7 +103,7 @@
     struct ContextInfo : public osg::Referenced
     {
         ContextInfo() : valid(UNKNOWN) {}
-        ContextInfo(const ContextInfo& rhs) : valid(rhs.valid()) {}
+        ContextInfo(const ContextInfo& rhs) : osg::Referenced(rhs), valid(rhs.valid()) {}
         ContextInfo& operator=(const ContextInfo& rhs)
         {
             valid = rhs.valid;

Modified: simgear/trunk/simgear/scene/material/TextureBuilder.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/TextureBuilder.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/TextureBuilder.cxx (original)
+++ simgear/trunk/simgear/scene/material/TextureBuilder.cxx Sun Jul 15 09:07:01 2012
@@ -32,12 +32,13 @@
 #include <osg/TextureRectangle>
 #include <osg/TextureCubeMap>
 #include <osgDB/FileUtils>
+#include <osgDB/ReadFile>
 
 #include <boost/lexical_cast.hpp>
 #include <boost/tuple/tuple.hpp>
 #include <boost/tuple/tuple_comparison.hpp>
 
-#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/scene/util/SGSceneFeatures.hxx>
 #include <simgear/scene/util/StateAttributeFactory.hxx>
 #include <simgear/math/SGMath.hxx>
@@ -54,13 +55,13 @@
 
 TexEnvCombine* buildTexEnvCombine(Effect* effect,
                                   const SGPropertyNode* envProp,
-                                  const SGReaderWriterXMLOptions* options);
+                                  const SGReaderWriterOptions* options);
 TexGen* buildTexGen(Effect* Effect, const SGPropertyNode* tgenProp);
 
 // Hack to force inclusion of TextureBuilder.cxx in library
 osg::Texture* TextureBuilder::buildFromType(Effect* effect, const string& type,
                                             const SGPropertyNode*props,
-                                            const SGReaderWriterXMLOptions*
+                                            const SGReaderWriterOptions*
                                             options)
 {
     return EffectBuilder<Texture>::buildFromType(effect, type, props, options);
@@ -102,7 +103,7 @@
 
 void TextureUnitBuilder::buildAttribute(Effect* effect, Pass* pass,
                                         const SGPropertyNode* prop,
-                                        const SGReaderWriterXMLOptions* options)
+                                        const SGReaderWriterOptions* options)
 {
     if (!isAttributeActive(effect, prop))
         return;
@@ -183,7 +184,7 @@
 EffectPropertyMap<Texture::WrapMode> wrapModes(wrapModesInit);
 
 TexTuple makeTexTuple(Effect* effect, const SGPropertyNode* props,
-                      const SGReaderWriterXMLOptions* options,
+                      const SGReaderWriterOptions* options,
                       const string& texType)
 {
     Texture::FilterMode minFilter = Texture::LINEAR_MIPMAP_LINEAR;
@@ -215,11 +216,14 @@
     if (pImage)
     {
         imageName = pImage->getStringValue();
-        absFileName = SGModelLib::findDataFile(imageName, options);
-        if (absFileName.empty())
+        if (!imageName.empty())
         {
-            SG_LOG(SG_INPUT, SG_ALERT, "Texture file not found: '"
-                   << imageName << "'");
+            absFileName = SGModelLib::findDataFile(imageName, options);
+            if (absFileName.empty())
+            {
+                SG_LOG(SG_INPUT, SG_ALERT, "Texture file not found: '"
+                       << imageName << "'");
+            }
         }
     }
 
@@ -234,14 +238,14 @@
 }
 
 void setAttrs(const TexTuple& attrs, Texture* tex,
-              const SGReaderWriterXMLOptions* options)
+              const SGReaderWriterOptions* options)
 {
     const string& imageName = attrs.get<0>();
     if (imageName.empty()) {
         throw BuilderException("no image file");
     } else {
-        osgDB::ReaderWriter::ReadResult result
-            = osgDB::Registry::instance()->readImage(imageName, options);
+        osgDB::ReaderWriter::ReadResult result;
+        result = osgDB::readImageFile(imageName, options);
         if (result.success()) {
             osg::ref_ptr<osg::Image> image = result.getImage();
             image = computeMipmap( image.get(), attrs.get<7>() );
@@ -275,7 +279,7 @@
 public:
     TexBuilder(const string& texType) : _type(texType) {}
     Texture* build(Effect* effect, const SGPropertyNode*,
-                   const SGReaderWriterXMLOptions* options);
+                   const SGReaderWriterOptions* options);
 protected:
     typedef map<TexTuple, ref_ptr<T> > TexMap;
     TexMap texMap;
@@ -284,7 +288,7 @@
 
 template<typename T>
 Texture* TexBuilder<T>::build(Effect* effect, const SGPropertyNode* props,
-                              const SGReaderWriterXMLOptions* options)
+                              const SGReaderWriterOptions* options)
 {
     TexTuple attrs = makeTexTuple(effect, props, options, _type);
     typename TexMap::iterator itr = texMap.find(attrs);
@@ -308,11 +312,11 @@
 {
 public:
     Texture* build(Effect* effect, const SGPropertyNode*,
-                   const SGReaderWriterXMLOptions* options);
+                   const SGReaderWriterOptions* options);
 };
 
 Texture* WhiteTextureBuilder::build(Effect* effect, const SGPropertyNode*,
-                                    const SGReaderWriterXMLOptions* options)
+                                    const SGReaderWriterOptions* options)
 {
     return StateAttributeFactory::instance()->getWhiteTexture();
 }
@@ -326,11 +330,11 @@
 {
 public:
     Texture* build(Effect* effect, const SGPropertyNode*,
-                   const SGReaderWriterXMLOptions* options);
+                   const SGReaderWriterOptions* options);
 };
 
 Texture* TransparentTextureBuilder::build(Effect* effect, const SGPropertyNode*,
-                                    const SGReaderWriterXMLOptions* options)
+                                    const SGReaderWriterOptions* options)
 {
     return StateAttributeFactory::instance()->getTransparentTexture();
 }
@@ -390,14 +394,14 @@
 {
 public:
     Texture* build(Effect* effect, const SGPropertyNode*,
-                   const SGReaderWriterXMLOptions* options);
+                   const SGReaderWriterOptions* options);
 protected:
     typedef map<int, ref_ptr<Texture3D> > NoiseMap;
     NoiseMap _noises;
 };
 
 Texture* NoiseBuilder::build(Effect* effect, const SGPropertyNode* props,
-                             const SGReaderWriterXMLOptions* options)
+                             const SGReaderWriterOptions* options)
 {
     int texSize = 64;
     const SGPropertyNode* sizeProp = getEffectPropertyChild(effect, props,
@@ -458,7 +462,7 @@
 {
 public:
     Texture* build(Effect* effect, const SGPropertyNode*,
-                   const SGReaderWriterXMLOptions* options);
+                   const SGReaderWriterOptions* options);
 protected:
     typedef map<CubeMapTuple, ref_ptr<TextureCubeMap> > CubeMap;
     typedef map<string, ref_ptr<TextureCubeMap> > CrossCubeMap;
@@ -481,7 +485,7 @@
 
 
 Texture* CubeMapBuilder::build(Effect* effect, const SGPropertyNode* props,
-                               const SGReaderWriterXMLOptions* options)
+                               const SGReaderWriterOptions* options)
 {
     // First check that there is a <images> tag
     const SGPropertyNode* texturesProp = getEffectPropertyChild(effect, props, "images");
@@ -511,33 +515,33 @@
         cubeTexture->setWrap(osg::Texture3D::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
         cubeTexture->setWrap(osg::Texture3D::WRAP_R, osg::Texture::CLAMP_TO_EDGE);
 
-        osgDB::ReaderWriter::ReadResult result =
-            osgDB::Registry::instance()->readImage(_tuple.get<0>(), options);
+        osgDB::ReaderWriter::ReadResult result;
+        result = osgDB::readImageFile(_tuple.get<0>(), options);
         if(result.success()) {
             osg::Image* image = result.getImage();
             cubeTexture->setImage(TextureCubeMap::POSITIVE_X, image);
         }
-        result = osgDB::Registry::instance()->readImage(_tuple.get<1>(), options);
+        result = osgDB::readImageFile(_tuple.get<1>(), options);
         if(result.success()) {
             osg::Image* image = result.getImage();
             cubeTexture->setImage(TextureCubeMap::NEGATIVE_X, image);
         }
-        result = osgDB::Registry::instance()->readImage(_tuple.get<2>(), options);
+        result = osgDB::readImageFile(_tuple.get<2>(), options);
         if(result.success()) {
             osg::Image* image = result.getImage();
             cubeTexture->setImage(TextureCubeMap::POSITIVE_Y, image);
         }
-        result = osgDB::Registry::instance()->readImage(_tuple.get<3>(), options);
+        result = osgDB::readImageFile(_tuple.get<3>(), options);
         if(result.success()) {
             osg::Image* image = result.getImage();
             cubeTexture->setImage(TextureCubeMap::NEGATIVE_Y, image);
         }
-        result = osgDB::Registry::instance()->readImage(_tuple.get<4>(), options);
+        result = osgDB::readImageFile(_tuple.get<4>(), options);
         if(result.success()) {
             osg::Image* image = result.getImage();
             cubeTexture->setImage(TextureCubeMap::POSITIVE_Z, image);
         }
-        result = osgDB::Registry::instance()->readImage(_tuple.get<5>(), options);
+        result = osgDB::readImageFile(_tuple.get<5>(), options);
         if(result.success()) {
             osg::Image* image = result.getImage();
             cubeTexture->setImage(TextureCubeMap::NEGATIVE_Z, image);
@@ -560,8 +564,8 @@
         if (itr != _crossmaps.end())
             return itr->second.get();
 
-        osgDB::ReaderWriter::ReadResult result =
-            osgDB::Registry::instance()->readImage(texname, options);
+        osgDB::ReaderWriter::ReadResult result;
+        result = osgDB::readImageFile(texname, options);
         if(result.success()) {
             osg::Image* image = result.getImage();
             image->flipVertical();   // Seems like the image coordinates are somewhat funny, flip to get better ones
@@ -690,7 +694,7 @@
 EffectPropertyMap<TexEnvCombine::OperandParam> operandParams(opParamInit);
 
 TexEnvCombine* buildTexEnvCombine(Effect* effect, const SGPropertyNode* envProp,
-                                  const SGReaderWriterXMLOptions* options)
+                                  const SGReaderWriterOptions* options)
 {
     if (!isAttributeActive(effect, envProp))
         return 0;

Modified: simgear/trunk/simgear/scene/material/TextureBuilder.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/TextureBuilder.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/TextureBuilder.hxx (original)
+++ simgear/trunk/simgear/scene/material/TextureBuilder.hxx Sun Jul 15 09:07:01 2012
@@ -29,13 +29,13 @@
     // Hack to force inclusion of TextureBuilder.cxx in library
     static osg::Texture* buildFromType(Effect* effect, const std::string& type,
                                        const SGPropertyNode*props,
-                                       const SGReaderWriterXMLOptions* options);
+                                       const SGReaderWriterOptions* options);
 };
 
 struct TextureUnitBuilder : public PassAttributeBuilder
 {
     void buildAttribute(Effect* effect, Pass* pass, const SGPropertyNode* prop,
-                        const SGReaderWriterXMLOptions* options);
+                        const SGReaderWriterOptions* options);
 };
 
 

Modified: simgear/trunk/simgear/scene/material/makeEffect.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/makeEffect.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/makeEffect.cxx (original)
+++ simgear/trunk/simgear/scene/material/makeEffect.cxx Sun Jul 15 09:07:01 2012
@@ -31,7 +31,7 @@
 #include <osgDB/Registry>
 
 #include <simgear/debug/logstream.hxx>
-#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/props/props_io.hxx>
 #include <simgear/scene/util/SGSceneFeatures.hxx>
 #include <simgear/scene/util/SplicingVisitor.hxx>
@@ -117,7 +117,7 @@
 
 Effect* makeEffect(const string& name,
                    bool realizeTechniques,
-                   const SGReaderWriterXMLOptions* options)
+                   const SGReaderWriterOptions* options)
 {
     {
         OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(effectMutex);
@@ -160,7 +160,7 @@
 
 Effect* makeEffect(SGPropertyNode* prop,
                    bool realizeTechniques,
-                   const SGReaderWriterXMLOptions* options)
+                   const SGReaderWriterOptions* options)
 {
     // Give default names to techniques and passes
     vector<SGPropertyNode_ptr> techniques = prop->getChildren("technique");

Modified: simgear/trunk/simgear/scene/material/mat.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/mat.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/mat.cxx (original)
+++ simgear/trunk/simgear/scene/material/mat.cxx Sun Jul 15 09:07:01 2012
@@ -49,7 +49,7 @@
 #include <simgear/debug/logstream.hxx>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/misc/sgstream.hxx>
-#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/props/props_io.hxx>
 #include <simgear/scene/model/model.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
@@ -69,13 +69,13 @@
 ////////////////////////////////////////////////////////////////////////
 
 SGMaterial::_internal_state::_internal_state(Effect *e, bool l,
-                                             const SGReaderWriterXMLOptions* o)
+                                             const SGReaderWriterOptions* o)
     : effect(e), effect_realized(l), options(o)
 {
 }
 
 SGMaterial::_internal_state::_internal_state(Effect *e, const string &t, bool l,
-                                             const SGReaderWriterXMLOptions* o)
+                                             const SGReaderWriterOptions* o)
     : effect(e), effect_realized(l), options(o)
 {
     texture_paths.push_back(std::make_pair(t,0));
@@ -86,7 +86,7 @@
     texture_paths.push_back(std::make_pair(t,i));
 }
 
-SGMaterial::SGMaterial( const SGReaderWriterXMLOptions* options,
+SGMaterial::SGMaterial( const SGReaderWriterOptions* options,
                         const SGPropertyNode *props )
 {
     init();
@@ -97,9 +97,9 @@
 SGMaterial::SGMaterial( const osgDB::ReaderWriter::Options* options,
                         const SGPropertyNode *props )
 {
-    osg::ref_ptr<const SGReaderWriterXMLOptions> sgOptions;
+    osg::ref_ptr<const SGReaderWriterOptions> sgOptions;
     if (options)
-        sgOptions = new SGReaderWriterXMLOptions(*options);
+        sgOptions = new SGReaderWriterOptions(*options);
     init();
     read_properties( sgOptions.get(), props );
     buildEffectProperties(sgOptions.get());
@@ -115,7 +115,7 @@
 ////////////////////////////////////////////////////////////////////////
 
 void
-SGMaterial::read_properties(const SGReaderWriterXMLOptions* options,
+SGMaterial::read_properties(const SGReaderWriterOptions* options,
                             const SGPropertyNode *props)
 {
 				// Gather the path(s) to the texture(s)
@@ -296,12 +296,12 @@
     return _status[i].effect.get();
 }
 
-void SGMaterial::buildEffectProperties(const SGReaderWriterXMLOptions* options)
+void SGMaterial::buildEffectProperties(const SGReaderWriterOptions* options)
 {
     using namespace osg;
-    ref_ptr<SGReaderWriterXMLOptions> xmlOptions;
+    ref_ptr<SGReaderWriterOptions> xmlOptions;
     if (options)
-        xmlOptions = new SGReaderWriterXMLOptions(*options);
+        xmlOptions = new SGReaderWriterOptions(*options);
     ref_ptr<SGMaterialUserData> user = new SGMaterialUserData(this);
     SGPropertyNode_ptr propRoot = new SGPropertyNode();
     makeChild(propRoot, "inherits-from")->setStringValue(effect);

Modified: simgear/trunk/simgear/scene/material/mat.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/mat.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/mat.hxx (original)
+++ simgear/trunk/simgear/scene/material/mat.hxx Sun Jul 15 09:07:01 2012
@@ -45,7 +45,7 @@
 class StateSet;
 }
 
-#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/structure/SGSharedPtr.hxx>
 #include <simgear/scene/util/SGSceneFeatures.hxx>
@@ -87,7 +87,7 @@
    */
   SGMaterial( const osgDB::ReaderWriter::Options*, const SGPropertyNode *props);
 
-  SGMaterial(const simgear::SGReaderWriterXMLOptions*,
+  SGMaterial(const simgear::SGReaderWriterOptions*,
              const SGPropertyNode *props);
   /**
    * Destructor.
@@ -273,14 +273,14 @@
 
   struct _internal_state {
       _internal_state(simgear::Effect *e, bool l,
-                      const simgear::SGReaderWriterXMLOptions *o);
+                      const simgear::SGReaderWriterOptions *o);
       _internal_state(simgear::Effect *e, const std::string &t, bool l,
-                      const simgear::SGReaderWriterXMLOptions *o);
+                      const simgear::SGReaderWriterOptions *o);
       void add_texture(const std::string &t, int i);
       osg::ref_ptr<simgear::Effect> effect;
       std::vector<std::pair<std::string,int> > texture_paths;
       bool effect_realized;
-      osg::ref_ptr<const simgear::SGReaderWriterXMLOptions> options;
+      osg::ref_ptr<const simgear::SGReaderWriterOptions> options;
   };
 
 private:
@@ -366,9 +366,9 @@
   // Internal constructors and methods.
   ////////////////////////////////////////////////////////////////////
 
-  void read_properties(const simgear::SGReaderWriterXMLOptions* options,
+  void read_properties(const simgear::SGReaderWriterOptions* options,
                         const SGPropertyNode *props);
-  void buildEffectProperties(const simgear::SGReaderWriterXMLOptions* options);
+  void buildEffectProperties(const simgear::SGReaderWriterOptions* options);
 };
 
 

Modified: simgear/trunk/simgear/scene/material/mipmap.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/mipmap.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/mipmap.cxx (original)
+++ simgear/trunk/simgear/scene/material/mipmap.cxx Sun Jul 15 09:07:01 2012
@@ -44,7 +44,7 @@
 EffectPropertyMap<MipMapFunction> mipmapFunctions(mipmapFunctionsInit);
 
 MipMapTuple makeMipMapTuple(Effect* effect, const SGPropertyNode* props,
-                      const SGReaderWriterXMLOptions* options)
+                      const SGReaderWriterOptions* options)
 {
     const SGPropertyNode* pMipmapR
         = getEffectPropertyChild(effect, props, "function-r");

Modified: simgear/trunk/simgear/scene/material/mipmap.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/material/mipmap.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/material/mipmap.hxx (original)
+++ simgear/trunk/simgear/scene/material/mipmap.hxx Sun Jul 15 09:07:01 2012
@@ -28,7 +28,7 @@
 namespace simgear
 {
 class Effect;
-class SGReaderWriterXMLOptions;
+class SGReaderWriterOptions;
 
 namespace effect {
 enum MipMapFunction {
@@ -43,7 +43,7 @@
 typedef boost::tuple<MipMapFunction, MipMapFunction, MipMapFunction, MipMapFunction> MipMapTuple;
 
 MipMapTuple makeMipMapTuple(Effect* effect, const SGPropertyNode* props,
-                      const SGReaderWriterXMLOptions* options);
+                      const SGReaderWriterOptions* options);
 osg::Image* computeMipmap( osg::Image* image, MipMapTuple attrs );
 } }
 

Modified: simgear/trunk/simgear/scene/model/CheckSceneryVisitor.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/model/CheckSceneryVisitor.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/model/CheckSceneryVisitor.cxx (original)
+++ simgear/trunk/simgear/scene/model/CheckSceneryVisitor.cxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,5 @@
 // Copyright (C) 2008 Till Busch buti at bux.at
+// Copyright (C) 2011 Mathias Froehlich
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
@@ -19,11 +20,12 @@
 #endif
 
 #include <osg/Transform>
+#include <osg/ProxyNode>
+#include <osgDB/DatabasePager>
 
 #include <simgear/debug/logstream.hxx>
 
 #include "CheckSceneryVisitor.hxx"
-#include "SGPagedLOD.hxx"
 
 #include <simgear/math/SGMath.hxx>
 
@@ -33,9 +35,10 @@
                                          osg::FrameStamp* framestamp)
 :osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR,
                   osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
-_position(position), _range(range), _loaded(true), _dbp(dbp), _framestamp(framestamp)
+ _position(position), _range(range), _loaded(true), _matrix(osg::Matrix::identity())
 {
-    _viewMatrices.push_back(osg::Matrix::identity());
+    setDatabaseRequestHandler(dbp);
+    setFrameStamp(framestamp);
 }
 
 void CheckSceneryVisitor::apply(osg::Node& node)
@@ -43,20 +46,53 @@
     traverse(node);
 }
 
+void CheckSceneryVisitor::apply(osg::ProxyNode& node)
+{
+    osg::Vec3 pos = node.getCenter() * _matrix;
+    double dist = (pos - _position).length();
+    if (dist < _range) {
+        for (unsigned i = 0; i < node.getNumFileNames(); ++i) {
+            if (node.getFileName(i).empty())
+                continue;
+            // Check if this is already loaded.
+            if (i < node.getNumChildren() && node.getChild(i))
+                continue;
+
+            // if the DatabasePager would load LODs while the splashscreen
+            // is there, we could just wait for the models to be loaded
+            // by only setting setLoaded(false) here
+            osg::NodePath nodePath = getNodePath();
+            DatabaseRequestHandler* db = getDatabaseRequestHandler();
+            const osg::FrameStamp* fs = getFrameStamp();
+            db->requestNodeFile(node.getFileName(i), nodePath, 1.0 /*priority*/, fs,
+                                node.getDatabaseRequest(i), node.getDatabaseOptions());
+            setLoaded(false);
+        }
+    }
+    traverse(node);
+}
+
 void CheckSceneryVisitor::apply(osg::PagedLOD& node)
 {
-    SGPagedLOD *sgplod = dynamic_cast<SGPagedLOD*>(&node);
-    if (sgplod) {
-        osg::Vec3 pos = sgplod->getCenter() * _viewMatrices.back();
-        double dist = (pos-_position).length();
-        if (dist < _range) {
-            if (sgplod->getNumChildren() < 1) {
-                // if the DatabasePager would load LODs while the splashscreen
-                // is there, we could just wait for the models to be loaded
-                // by only setting setLoaded(false) here
-                sgplod->forceLoad(_dbp,_framestamp, getNodePath());
-                setLoaded(false);
-            }
+    osg::Vec3 pos = node.getCenter() * _matrix;
+    double dist = (pos - _position).length();
+    if (dist < _range) {
+        for (unsigned i = 0; i < node.getNumFileNames(); ++i) {
+            if (node.getFileName(i).empty())
+                continue;
+            // Check if this is already loaded.
+            if (i < node.getNumChildren() && node.getChild(i))
+                continue;
+
+            // if the DatabasePager would load LODs while the splashscreen
+            // is there, we could just wait for the models to be loaded
+            // by only setting setLoaded(false) here
+            osg::NodePath nodePath = getNodePath();
+            DatabaseRequestHandler* db = getDatabaseRequestHandler();
+            const osg::FrameStamp* fs = getFrameStamp();
+            db->requestNodeFile(node.getFileName(i), nodePath, 1.0 /*priority*/, fs,
+                                node.getDatabaseRequest(i), node.getDatabaseOptions());
+            setLoaded(false);
         }
     }
     traverse(node);
@@ -64,14 +100,8 @@
 
 void CheckSceneryVisitor::apply(osg::Transform &node)
 {
-    osg::Matrix currMatrix = _viewMatrices.back();
-    bool pushMatrix = node.computeLocalToWorldMatrix(currMatrix, this);
-
-    if (pushMatrix) {
-        _viewMatrices.push_back(currMatrix);
-    }
+    osg::Matrix matrix = _matrix;
+    node.computeLocalToWorldMatrix(_matrix, this);
     traverse(node);
-    if (pushMatrix) {
-        _viewMatrices.pop_back();
-    }
+    _matrix = matrix;
 }

Modified: simgear/trunk/simgear/scene/model/CheckSceneryVisitor.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/model/CheckSceneryVisitor.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/model/CheckSceneryVisitor.hxx (original)
+++ simgear/trunk/simgear/scene/model/CheckSceneryVisitor.hxx Sun Jul 15 09:07:01 2012
@@ -1,4 +1,5 @@
 // Copyright (C) 2008 Till Busch buti at bux.at
+// Copyright (C) 2011 Mathias Froehlich
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
@@ -18,7 +19,6 @@
 #define CHECKSCENERYVISITOR_HXX
 
 #include <osg/NodeVisitor>
-#include <osg/fast_back_stack>
 
 namespace osgDB {
 class DatabasePager;
@@ -28,9 +28,7 @@
 namespace simgear
 {
 
-class SGPagedLOD;
-
-// Checks the scene graph for SGPagedLODs that are within range
+// Checks the scene graph for PagedLOD or ProxyNodes that are within range
 // (compared to postion) and injects them into the DatabasePager.
 // After visiting, isLoaded() returns true if all models in range
 // are available.
@@ -41,6 +39,7 @@
     CheckSceneryVisitor(osgDB::DatabasePager* dbp, const osg::Vec3 &position, double range, osg::FrameStamp* framestamp);
 
     virtual void apply(osg::Node& node);
+    virtual void apply(osg::ProxyNode& node);
     virtual void apply(osg::PagedLOD& node);
     virtual void apply(osg::Transform& node);
 
@@ -58,10 +57,7 @@
     osg::Vec3 _position;
     double _range;
     bool _loaded;
-    osgDB::DatabasePager* _dbp;
-    osg::FrameStamp* _framestamp;
-
-    osg::fast_back_stack<osg::Matrix> _viewMatrices;
+    osg::Matrix _matrix;
 };
 
 }

Modified: simgear/trunk/simgear/scene/model/ModelRegistry.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/model/ModelRegistry.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/model/ModelRegistry.cxx (original)
+++ simgear/trunk/simgear/scene/model/ModelRegistry.cxx Sun Jul 15 09:07:01 2012
@@ -47,6 +47,7 @@
 #include <simgear/scene/util/SGSceneFeatures.hxx>
 #include <simgear/scene/util/SGStateAttributeVisitor.hxx>
 #include <simgear/scene/util/SGTextureStateAttributeVisitor.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/scene/util/NodeAndDrawableVisitor.hxx>
 
 #include <simgear/structure/exception.hxx>
@@ -56,7 +57,6 @@
 
 #include "BoundingVolumeBuildVisitor.hxx"
 #include "model.hxx"
-#include "SGReaderWriterXMLOptions.hxx"
 
 using namespace std;
 using namespace osg;
@@ -231,6 +231,69 @@
             SG_LOG(SG_IO, SG_BULK, "Reading image \""
                    << res.getImage()->getFileName() << "\"");
 
+        // Check for precompressed textures that depend on an extension
+        switch (res.getImage()->getPixelFormat()) {
+
+            // GL_EXT_texture_compression_s3tc
+            // patented, no way to decompress these
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
+#endif
+        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+        case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+        case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+            
+            // GL_EXT_texture_sRGB
+            // patented, no way to decompress these
+#ifndef GL_EXT_texture_sRGB
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT  0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#endif
+        case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+            
+            // GL_TDFX_texture_compression_FXT1
+            // can decompress these in software but
+            // no code present in simgear.
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_COMPRESSED_RGB_FXT1_3DFX       0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX      0x86B1
+#endif
+        case GL_COMPRESSED_RGB_FXT1_3DFX:
+        case GL_COMPRESSED_RGBA_FXT1_3DFX:
+            
+            // GL_EXT_texture_compression_rgtc
+            // can decompress these in software but
+            // no code present in simgear.
+#ifndef GL_EXT_texture_compression_rgtc
+#define GL_COMPRESSED_RED_RGTC1_EXT       0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#endif
+        case GL_COMPRESSED_RED_RGTC1_EXT:
+        case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+        case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+        case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+
+            SG_LOG(SG_IO, SG_WARN, "Image \"" << fileName << "\"\n"
+                   "uses compressed textures which cannot be supported on "
+                   "some systems.\n"
+                   "Please decompress this texture for improved portability.");
+            break;
+
+        default:
+            break;
+        }
+
         return res;
     }
 }
@@ -410,8 +473,8 @@
                 && group->getNumChildren() == 1)
                 optimized = static_cast<Node*>(group->getChild(0));
         }
-        const SGReaderWriterXMLOptions* sgopt
-            = dynamic_cast<const SGReaderWriterXMLOptions*>(opt);
+        const SGReaderWriterOptions* sgopt
+            = dynamic_cast<const SGReaderWriterOptions*>(opt);
         if (sgopt && sgopt->getInstantiateEffects())
             optimized = instantiateEffects(optimized.get(), sgopt);
         return optimized.release();

Modified: simgear/trunk/simgear/scene/model/SGReaderWriterXML.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/model/SGReaderWriterXML.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/model/SGReaderWriterXML.cxx (original)
+++ simgear/trunk/simgear/scene/model/SGReaderWriterXML.cxx Sun Jul 15 09:07:01 2012
@@ -29,6 +29,7 @@
 
 #include <osg/Geode>
 #include <osg/MatrixTransform>
+#include <osgDB/ReadFile>
 #include <osgDB/WriteFile>
 #include <osgDB/Registry>
 #include <osg/Switch>
@@ -40,11 +41,10 @@
 #include <simgear/props/props_io.hxx>
 #include <simgear/props/condition.hxx>
 #include <simgear/scene/util/SGNodeMasks.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 
 #include "modellib.hxx"
-#include "SGPagedLOD.hxx"
 #include "SGReaderWriterXML.hxx"
-#include "SGReaderWriterXMLOptions.hxx"
 
 #include "animation.hxx"
 #include "particles.hxx"
@@ -208,8 +208,8 @@
       return NULL;
     }
     
-    const SGReaderWriterXMLOptions* xmlOptions;
-    xmlOptions = dynamic_cast<const SGReaderWriterXMLOptions*>(options_);
+    const SGReaderWriterOptions* xmlOptions;
+    xmlOptions = dynamic_cast<const SGReaderWriterOptions*>(options_);
 
     SGSharedPtr<SGPropertyNode> prop_root;
     osg::Node *(*load_panel)(SGPropertyNode *)=0;
@@ -219,7 +219,7 @@
     SGPath modelDir(modelpath.dir());
     
     if (xmlOptions) {
-        prop_root = xmlOptions->getPropRoot();
+        prop_root = xmlOptions->getPropertyNode();
         load_panel = xmlOptions->getLoadPanel();
         data = xmlOptions->getModelData();
     }
@@ -269,9 +269,9 @@
         // model without wrapper
     }
 
-    osg::ref_ptr<SGReaderWriterXMLOptions> options
-    = new SGReaderWriterXMLOptions(*options_);
-    options->setPropRoot(prop_root);
+    osg::ref_ptr<SGReaderWriterOptions> options
+    = new SGReaderWriterOptions(*options_);
+    options->setPropertyNode(prop_root);
     options->setLoadPanel(load_panel);
     
     // Assume that textures are in
@@ -281,9 +281,8 @@
             texturepath = texturepath.dir();
 
         options->setDatabasePath(texturepath.str());
-        osgDB::ReaderWriter::ReadResult modelResult
-            = osgDB::Registry::instance()->readNode(modelpath.str(),
-                                                    options.get());
+        osgDB::ReaderWriter::ReadResult modelResult;
+        modelResult = osgDB::readNodeFile(modelpath.str(), options.get());
         if (!modelResult.validNode())
             throw sg_io_exception("Failed to load 3D model:" + modelResult.message(),
                                   modelpath.str());
@@ -354,9 +353,9 @@
           continue;
         }
 
-        osg::ref_ptr<SGReaderWriterXMLOptions> options;
-        options = new SGReaderWriterXMLOptions(*options_);
-        options->setPropRoot(prop_root);
+        osg::ref_ptr<SGReaderWriterOptions> options;
+        options = new SGReaderWriterOptions(*options_);
+        options->setPropertyNode(prop_root);
         options->setLoadPanel(load_panel);
         
         try {

Modified: simgear/trunk/simgear/scene/model/model.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/model/model.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/model/model.cxx (original)
+++ simgear/trunk/simgear/scene/model/model.cxx Sun Jul 15 09:07:01 2012
@@ -25,7 +25,7 @@
 #include <simgear/scene/util/SGSceneUserData.hxx>
 #include <simgear/scene/util/CopyOp.hxx>
 #include <simgear/scene/util/SplicingVisitor.hxx>
-
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 
 #include <simgear/structure/exception.hxx>
 #include <simgear/structure/Singleton.hxx>
@@ -33,7 +33,6 @@
 #include <simgear/props/props_io.hxx>
 #include <simgear/props/condition.hxx>
 
-#include "SGReaderWriterXMLOptions.hxx"
 #include "model.hxx"
 
 using std::vector;
@@ -210,7 +209,7 @@
 public:
     typedef std::map<string, SGPropertyNode_ptr> EffectMap;
     using SplicingVisitor::apply;
-    MakeEffectVisitor(const SGReaderWriterXMLOptions* options = 0)
+    MakeEffectVisitor(const SGReaderWriterOptions* options = 0)
         : _options(options)
     {
     }
@@ -226,7 +225,7 @@
 protected:
     EffectMap _effectMap;
     SGPropertyNode_ptr _currentEffectParent;
-    osg::ref_ptr<const SGReaderWriterXMLOptions> _options;
+    osg::ref_ptr<const SGReaderWriterOptions> _options;
 };
 
 void MakeEffectVisitor::apply(osg::Group& node)
@@ -309,7 +308,7 @@
 
 ref_ptr<Node> instantiateEffects(osg::Node* modelGroup,
                                  PropertyList& effectProps,
-                                 const SGReaderWriterXMLOptions* options)
+                                 const SGReaderWriterOptions* options)
 {
     SGPropertyNode_ptr defaultEffectPropRoot;
     MakeEffectVisitor visitor(options);

Modified: simgear/trunk/simgear/scene/model/model.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/model/model.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/model/model.hxx (original)
+++ simgear/trunk/simgear/scene/model/model.hxx Sun Jul 15 09:07:01 2012
@@ -25,7 +25,7 @@
 
 namespace simgear
 {
-class SGReaderWriterXMLOptions;
+class SGReaderWriterOptions;
 }
 
 osg::Texture2D*
@@ -102,7 +102,7 @@
 osg::ref_ptr<osg::Node>
 instantiateEffects(osg::Node* model,
                    PropertyList& effectProps,
-                   const SGReaderWriterXMLOptions* options);
+                   const SGReaderWriterOptions* options);
 
 /**
  * Transform an OSG subgraph by substituting the Effects and
@@ -115,7 +115,7 @@
 
 inline osg::ref_ptr<osg::Node>
 instantiateEffects(osg::Node* model,
-                   const SGReaderWriterXMLOptions* options)
+                   const SGReaderWriterOptions* options)
 {
     PropertyList effectProps;
     return instantiateEffects(model, effectProps, options);

Modified: simgear/trunk/simgear/scene/model/modellib.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/model/modellib.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/model/modellib.cxx (original)
+++ simgear/trunk/simgear/scene/model/modellib.cxx Sun Jul 15 09:07:01 2012
@@ -21,6 +21,8 @@
 
 #include <boost/algorithm/string.hpp>
 
+#include <osg/PagedLOD>
+#include <osg/ProxyNode>
 #include <osgDB/ReadFile>
 #include <osgDB/WriteFile>
 #include <osgDB/Registry>
@@ -30,11 +32,10 @@
 #include <simgear/props/props_io.hxx>
 #include <simgear/scene/model/model.hxx>
 #include <simgear/scene/model/ModelRegistry.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/misc/ResourceManager.hxx>
 
-#include "SGPagedLOD.hxx"
 #include "SGReaderWriterXML.hxx"
-#include "SGReaderWriterXMLOptions.hxx"
 
 #include "modellib.hxx"
 
@@ -56,7 +57,6 @@
 {
     osgDB::Registry::instance()->getDataFilePathList().push_front(root_dir);
     static_propRoot = root;
-    SGPagedLOD::setRenderingCache(root->getBoolValue("/sim/rendering/cache",true));
 }
 
 void SGModelLib::setPanelFunc(panel_func pf)
@@ -87,7 +87,7 @@
 
 namespace
 {
-osg::Node* loadFile(const string& path, SGReaderWriterXMLOptions* options)
+osg::Node* loadFile(const string& path, SGReaderWriterOptions* options)
 {
     using namespace osg;
     using namespace osgDB;
@@ -107,8 +107,8 @@
                        SGModelData *data,
                        bool load2DPanels)
 {
-    osg::ref_ptr<SGReaderWriterXMLOptions> opt = new SGReaderWriterXMLOptions(*(osgDB::Registry::instance()->getOptions()));
-    opt->setPropRoot(prop_root ? prop_root: static_propRoot.get());
+    osg::ref_ptr<SGReaderWriterOptions> opt = new SGReaderWriterOptions(*(osgDB::Registry::instance()->getOptions()));
+    opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
     opt->setModelData(data);
     
     if (load2DPanels) {
@@ -123,23 +123,52 @@
 }
 
 osg::Node*
+SGModelLib::loadDeferredModel(const string &path, SGPropertyNode *prop_root,
+                             SGModelData *data)
+{
+    osg::ProxyNode* proxyNode = new osg::ProxyNode;
+    proxyNode->setLoadingExternalReferenceMode(osg::ProxyNode::DEFER_LOADING_TO_DATABASE_PAGER);
+    proxyNode->setFileName(0, path);
+
+    osg::ref_ptr<SGReaderWriterOptions> opt
+        = new SGReaderWriterOptions(*(osgDB::Registry::instance()
+                                         ->getOptions()));
+    opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
+    opt->setModelData(data);
+    opt->setLoadPanel(static_panelFunc);
+    if (SGPath(path).lower_extension() == "ac")
+        opt->setInstantiateEffects(true);
+    if (!prop_root || prop_root->getBoolValue("/sim/rendering/cache", true))
+        opt->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL);
+    else
+        opt->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_NONE);
+    proxyNode->setDatabaseOptions(opt.get());
+
+    return proxyNode;
+}
+
+osg::Node*
 SGModelLib::loadPagedModel(const string &path, SGPropertyNode *prop_root,
                            SGModelData *data)
 {
-    SGPagedLOD *plod = new SGPagedLOD;
+    osg::PagedLOD *plod = new osg::PagedLOD;
     plod->setName("Paged LOD for \"" + path + "\"");
     plod->setFileName(0, path);
     plod->setRange(0, 0.0, 50.0*SG_NM_TO_METER);
 
-    osg::ref_ptr<SGReaderWriterXMLOptions> opt
-        = new SGReaderWriterXMLOptions(*(osgDB::Registry::instance()
+    osg::ref_ptr<SGReaderWriterOptions> opt
+        = new SGReaderWriterOptions(*(osgDB::Registry::instance()
                                          ->getOptions()));
-    opt->setPropRoot(prop_root ? prop_root: static_propRoot.get());
+    opt->setPropertyNode(prop_root ? prop_root: static_propRoot.get());
     opt->setModelData(data);
     opt->setLoadPanel(static_panelFunc);
-    if (boost::iends_with(path, ".ac"))
+    if (SGPath(path).lower_extension() == "ac")
         opt->setInstantiateEffects(true);
-    plod->setReaderWriterOptions(opt.get());
+    if (!prop_root || prop_root->getBoolValue("/sim/rendering/cache", true))
+        opt->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL);
+    else
+        opt->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_NONE);
+    plod->setDatabaseOptions(opt.get());
     return plod;
 }
 

Modified: simgear/trunk/simgear/scene/model/modellib.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/model/modellib.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/model/modellib.hxx (original)
+++ simgear/trunk/simgear/scene/model/modellib.hxx Sun Jul 15 09:07:01 2012
@@ -55,11 +55,17 @@
                                 SGModelData *data=0, bool load2DPanels=false);
 
     // Load a 3D model (any format) through the DatabasePager.
-    // Most models should be loaded using this function!
-    // This function will initially return an SGPagedLOD node.
-    // data->modelLoaded() will be called after the model is loaded and
-    // connected to the scene graph. See AIModelData on how to use this.
-    // NOTE: AIModelData uses observer_ptr to avoid circular references.
+    // This function initially just returns a proxy node that refers to
+    // the model file. Once the viewer steps onto that node the
+    // model will be loaded.
+    static osg::Node* loadDeferredModel(const std::string &path,
+                                        SGPropertyNode *prop_root = NULL,
+                                        SGModelData *data=0);
+    // Load a 3D model (any format) through the DatabasePager.
+    // This function initially just returns a PagedLOD node that refers to
+    // the model file. Once the viewer steps onto that node the
+    // model will be loaded. When the viewer does no longer reference this
+    // node for a long time the node is unloaded again.
     static osg::Node* loadPagedModel(const std::string &path,
                                      SGPropertyNode *prop_root = NULL,
                                      SGModelData *data=0);

Modified: simgear/trunk/simgear/scene/model/placement.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/model/placement.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/model/placement.cxx (original)
+++ simgear/trunk/simgear/scene/model/placement.cxx Sun Jul 15 09:07:01 2012
@@ -25,6 +25,7 @@
     _selector(new osg::Switch),
     _transform(new osg::PositionAttitudeTransform)
 {
+    _selector->addChild(_transform.get());
 }
 
 SGModelPlacement::~SGModelPlacement ()
@@ -34,10 +35,11 @@
 void
 SGModelPlacement::init( osg::Node * model )
 {
+  // remove previous model (in case of reinit)
+  _transform->removeChild(0,1);
   if (model != 0) {
       _transform->addChild(model);
   }
-  _selector->addChild(_transform.get());
   _selector->setValue(0, 1);
 }
 

Modified: simgear/trunk/simgear/scene/sky/CloudShaderGeometry.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/CloudShaderGeometry.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/CloudShaderGeometry.cxx (original)
+++ simgear/trunk/simgear/scene/sky/CloudShaderGeometry.cxx Sun Jul 15 09:07:01 2012
@@ -110,20 +110,24 @@
         const CloudSprite& t = _cloudsprites[itr->idx];
         GLfloat ua1[3] = { (GLfloat) t.texture_index_x/varieties_x,
                            (GLfloat) t.texture_index_y/varieties_y,
-			   (GLfloat) t.width };
+                           (GLfloat) t.width };
         GLfloat ua2[3] = { (GLfloat) t.height,
-		           (GLfloat) t.shade,
-                           (GLfloat) t.cloud_height };
+		                       (GLfloat) shade_factor,
+                           (GLfloat) cloud_height };
+        GLfloat ua3[3] = { (GLfloat) bottom_factor,
+                           (GLfloat) middle_factor,
+                           (GLfloat) top_factor };
+                           
         extensions->glVertexAttrib3fv(USR_ATTR_1, ua1 );
         extensions->glVertexAttrib3fv(USR_ATTR_2, ua2 );
-        glColor4f(t.position.x(), t.position.y(), t.position.z(), 1.0);
+        extensions->glVertexAttrib3fv(USR_ATTR_3, ua3 );
+        glColor4f(t.position.x(), t.position.y(), t.position.z(), zscale);
         _geometry->draw(renderInfo);
     }
 }
 
 void CloudShaderGeometry::addSprite(const SGVec3f& p, int tx, int ty,
-                                    float w, float h,
-                                    float s, float cull, float cloud_height)
+                                    float w, float h, float cull)
 {
     // Only add the sprite if it is further than the cull distance to all other sprites
     // except for the center sprite.	
@@ -137,8 +141,8 @@
             return;
         }
     }
-
-    _cloudsprites.push_back(CloudSprite(p, tx, ty, w, h, s, cloud_height));
+    
+    _cloudsprites.push_back(CloudSprite(p, tx, ty, w, h));
 }
 
 bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
@@ -166,13 +170,13 @@
         while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
             SGVec3f v;
             int tx, ty;
-            float w, h, s, ch;
+            float w, h;
             if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
                 && fr[2].getFloat(v.z()) && fr[3].getInt(tx) && fr[4].getInt(ty) &&  
-                fr[5].getFloat(w) && fr[6].getFloat(h)&& fr[7].getFloat(s) && fr[8].getFloat(ch)) {
+                fr[5].getFloat(w) && fr[6].getFloat(h)) {
                     fr += 5;
                     //SGVec3f* v = new SGVec3f(v.x(), v.y(), v.z());
-                    geom._cloudsprites.push_back(CloudShaderGeometry::CloudSprite(v, tx, ty, w, h,s,ch));
+                    geom._cloudsprites.push_back(CloudShaderGeometry::CloudSprite(v, tx, ty, w, h));
             } else {
                 ++fr;
             }
@@ -197,8 +201,7 @@
              fw.indent() << itr->position.x() << " " << itr->position.y() << " " 
                      << itr->position.z() << " " << itr->texture_index_x << " "
                      << itr->texture_index_y << " "  << itr->width << " " 
-                     << itr->height << " " << itr->shade 
-                     << itr->cloud_height << " "<< std::endl;
+                     << itr->height << " " << std::endl;
     }
     fw.moveOut();
     fw.indent() << "}" << std::endl;

Modified: simgear/trunk/simgear/scene/sky/CloudShaderGeometry.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/CloudShaderGeometry.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/CloudShaderGeometry.hxx (original)
+++ simgear/trunk/simgear/scene/sky/CloudShaderGeometry.hxx Sun Jul 15 09:07:01 2012
@@ -46,14 +46,15 @@
         
         const static unsigned int USR_ATTR_1 = 10;
         const static unsigned int USR_ATTR_2 = 11;
-        
+        const static unsigned int USR_ATTR_3 = 12;
+                
         CloudShaderGeometry()
         { 
             setUseDisplayList(false); 
         }
 
-        CloudShaderGeometry(int vx, int vy, float width, float height) :
-            varieties_x(vx), varieties_y(vy)
+        CloudShaderGeometry(int vx, int vy, float width, float height, float ts, float ms, float bs, float shade, float ch, float zsc) :
+            varieties_x(vx), varieties_y(vy), top_factor(ts), middle_factor(ms), bottom_factor(bs), shade_factor(shade), cloud_height(ch), zscale(zsc)
         { 
             setUseDisplayList(false); 
             float x = width/2.0f;
@@ -69,9 +70,8 @@
         META_Object(flightgear, CloudShaderGeometry);
         
         struct CloudSprite {
-            CloudSprite(const SGVec3f& p, int tx, int ty, float w, float h,
-                        float s, float ch) :
-                    position(p), texture_index_x(tx), texture_index_y(ty), width(w), height(h), shade(s), cloud_height(ch)
+            CloudSprite(const SGVec3f& p, int tx, int ty, float w, float h) :
+                    position(p), texture_index_x(tx), texture_index_y(ty), width(w), height(h)
                     { }
         
                     SGVec3f position;
@@ -79,8 +79,6 @@
                     int texture_index_y;
                     float width;
                     float height;
-                    float shade;
-                    float cloud_height;
         };
         
         typedef std::vector<CloudSprite> CloudSpriteList;
@@ -88,8 +86,8 @@
         
         void insert(const CloudSprite& t)
         { _cloudsprites.push_back(t); }
-        void insert(SGVec3f& p, int tx, int ty, float w, float h, float s, float ch)
-        { insert(CloudSprite(p, tx, ty, w, h, s, ch)); }
+        void insert(SGVec3f& p, int tx, int ty, float w, float h)
+        { insert(CloudSprite(p, tx, ty, w, h)); }
         
         unsigned getNumCloudSprite() const
         { return _cloudsprites.size(); }
@@ -107,14 +105,19 @@
             _geometry = geometry;
         }
         
-    void addSprite(const SGVec3f& p, int tx, int ty, float w, float h,
-                   float s, float cull, float cloud_height);
+        void addSprite(const SGVec3f& p, int tx, int ty, float w, float h, float cull);
                 
         osg::ref_ptr<osg::Drawable> _geometry;
 
         int varieties_x;
         int varieties_y;
-        
+        float top_factor;
+        float middle_factor;
+        float bottom_factor;
+        float shade_factor;
+        float cloud_height;
+        float zscale;
+                
         // Bounding box extents.
         osg::BoundingBox _bbox;
         

Modified: simgear/trunk/simgear/scene/sky/cloud.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/cloud.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/cloud.cxx (original)
+++ simgear/trunk/simgear/scene/sky/cloud.cxx Sun Jul 15 09:07:01 2012
@@ -48,7 +48,7 @@
 #endif
 
 #include <simgear/math/sg_random.h>
-#include <simgear/misc/PathOptions.hxx>
+#include <simgear/scene/util/PathOptions.hxx>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/scene/model/model.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
@@ -78,9 +78,6 @@
 static osg::ref_ptr<osg::StateSet> layer_states2[SGCloudLayer::SG_MAX_CLOUD_COVERAGES];
 static osg::ref_ptr<osg::TextureCubeMap> cubeMap;
 static bool state_initialized = false;
-static bool bump_mapping = false;
-
-bool SGCloudLayer::enable_bump_mapping = false;
 
 const std::string SGCloudLayer::SG_CLOUD_OVERCAST_STRING = "overcast";
 const std::string SGCloudLayer::SG_CLOUD_BROKEN_STRING = "broken";
@@ -380,18 +377,6 @@
         state_initialized = true;
 
         SG_LOG(SG_ASTRO, SG_INFO, "initializing cloud layers");
-
-        osg::Texture::Extensions* extensions;
-        extensions = osg::Texture::getExtensions(0, true);
-        // OSGFIXME
-        bump_mapping = extensions->isMultiTexturingSupported() &&
-          (2 <= extensions->numTextureUnits()) &&
-          SGIsOpenGLExtensionSupported("GL_ARB_texture_env_combine") &&
-          SGIsOpenGLExtensionSupported("GL_ARB_texture_env_dot3");
-
-        osg::TextureCubeMap::Extensions* extensions2;
-        extensions2 = osg::TextureCubeMap::getExtensions(0, true);
-        bump_mapping = bump_mapping && extensions2->isCubeMapSupported();
 
         // This bump mapping code was inspired by the tutorial available at 
         // http://www.paulsprojects.net/tutorials/simplebump/simplebump.html
@@ -675,138 +660,142 @@
 bool SGCloudLayer::reposition( const SGVec3f& p, const SGVec3f& up, double lon, double lat,
         		       double alt, double dt )
 {
-    // combine p and asl (meters) to get translation offset
-    osg::Vec3 asl_offset(toOsg(up));
-    asl_offset.normalize();
-    if ( alt <= layer_asl ) {
-        asl_offset *= layer_asl;
-    } else {
-        asl_offset *= layer_asl + layer_thickness;
-    }
-
-    // cout << "asl_offset = " << asl_offset[0] << "," << asl_offset[1]
-    //      << "," << asl_offset[2] << endl;
-    asl_offset += toOsg(p);
-    // cout << "  asl_offset = " << asl_offset[0] << "," << asl_offset[1]
-    //      << "," << asl_offset[2] << endl;
-
-    osg::Matrix T, LON, LAT;
-    // Translate to zero elevation
-    // Point3D zero_elev = current_view.get_cur_zero_elev();
-    T.makeTranslate( asl_offset );
-
-    // printf("  Translated to %.2f %.2f %.2f\n", 
-    //        zero_elev.x, zero_elev.y, zero_elev.z );
-
-    // Rotate to proper orientation
-    // printf("  lon = %.2f  lat = %.2f\n", 
-    //        lon * SGD_RADIANS_TO_DEGREES,
-    //        lat * SGD_RADIANS_TO_DEGREES);
-    LON.makeRotate(lon, osg::Vec3(0, 0, 1));
-
-    // xglRotatef( 90.0 - f->get_Latitude() * SGD_RADIANS_TO_DEGREES,
-    //             0.0, 1.0, 0.0 );
-    LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
-
-    layer_transform->setMatrix( LAT*LON*T );
-
-    // The layers need to be drawn in order because they are
-    // translucent, but OSG transparency sorting doesn't work because
-    // the cloud polys are huge. However, the ordering is simple: the
-    // bottom polys should be drawn from high altitude to low, and the
-    // top polygons from low to high. The altitude can be used
-    // directly to order the polygons!
-    group_bottom->getStateSet()->setRenderBinDetails(-(int)layer_asl,
-                                                     "RenderBin");
-    group_top->getStateSet()->setRenderBinDetails((int)layer_asl,
-                                                  "RenderBin");
-    if ( alt <= layer_asl ) {
-      layer_root->setSingleChildOn(0);
-    } else if ( alt >= layer_asl + layer_thickness ) {
-      layer_root->setSingleChildOn(1);
-    } else {
-      layer_root->setAllChildrenOff();
-    }
+  
+    if (getCoverage() != SGCloudLayer::SG_CLOUD_CLEAR)
+    {
+        // combine p and asl (meters) to get translation offset
+        osg::Vec3 asl_offset(toOsg(up));
+        asl_offset.normalize();
+        if ( alt <= layer_asl ) {
+            asl_offset *= layer_asl;
+        } else {
+            asl_offset *= layer_asl + layer_thickness;
+        }
+
+        // cout << "asl_offset = " << asl_offset[0] << "," << asl_offset[1]
+        //      << "," << asl_offset[2] << endl;
+        asl_offset += toOsg(p);
+        // cout << "  asl_offset = " << asl_offset[0] << "," << asl_offset[1]
+        //      << "," << asl_offset[2] << endl;
+
+        osg::Matrix T, LON, LAT;
+        // Translate to zero elevation
+        // Point3D zero_elev = current_view.get_cur_zero_elev();
+        T.makeTranslate( asl_offset );
+
+        // printf("  Translated to %.2f %.2f %.2f\n", 
+        //        zero_elev.x, zero_elev.y, zero_elev.z );
+
+        // Rotate to proper orientation
+        // printf("  lon = %.2f  lat = %.2f\n", 
+        //        lon * SGD_RADIANS_TO_DEGREES,
+        //        lat * SGD_RADIANS_TO_DEGREES);
+        LON.makeRotate(lon, osg::Vec3(0, 0, 1));
+
+        // xglRotatef( 90.0 - f->get_Latitude() * SGD_RADIANS_TO_DEGREES,
+        //             0.0, 1.0, 0.0 );
+        LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
+
+        layer_transform->setMatrix( LAT*LON*T );
+
+        // The layers need to be drawn in order because they are
+        // translucent, but OSG transparency sorting doesn't work because
+        // the cloud polys are huge. However, the ordering is simple: the
+        // bottom polys should be drawn from high altitude to low, and the
+        // top polygons from low to high. The altitude can be used
+        // directly to order the polygons!
+        group_bottom->getStateSet()->setRenderBinDetails(-(int)layer_asl,
+                                                         "RenderBin");
+        group_top->getStateSet()->setRenderBinDetails((int)layer_asl,
+                                                      "RenderBin");
+        if ( alt <= layer_asl ) {
+          layer_root->setSingleChildOn(0);
+        } else if ( alt >= layer_asl + layer_thickness ) {
+          layer_root->setSingleChildOn(1);
+        } else {
+          layer_root->setAllChildrenOff();
+        }
+            
+
+        // now calculate update texture coordinates
+        SGGeod pos = SGGeod::fromRad(lon, lat);
+        if ( last_pos == SGGeod() ) {
+            last_pos = pos;
+        }
+
+        double sp_dist = speed*dt;
         
-
-    // now calculate update texture coordinates
-    SGGeod pos = SGGeod::fromRad(lon, lat);
-    if ( last_pos == SGGeod() ) {
-        last_pos = pos;
-    }
-
-    double sp_dist = speed*dt;
-    
-    
-    if ( lon != last_pos.getLongitudeRad() || lat != last_pos.getLatitudeRad() || sp_dist != 0 ) {
-        double course = SGGeodesy::courseDeg(last_pos, pos) * SG_DEGREES_TO_RADIANS, 
-            dist = SGGeodesy::distanceM(last_pos, pos);
-
-        // if start and dest are too close together,
-        // calc_gc_course_dist() can return a course of "nan".  If
-        // this happens, lets just use the last known good course.
-        // This is a hack, and it would probably be better to make
-        // calc_gc_course_dist() more robust.
-        if ( isnan(course) ) {
-            course = last_course;
-        } else {
-            last_course = course;
-        }
-
-        // calculate cloud movement due to external forces
-        double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0;
-
-        if (dist > 0.0) {
-            ax = -cos(course) * dist;
-            ay = sin(course) * dist;
-        }
-
-        if (sp_dist > 0) {
-            bx = cos((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
-            by = sin((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
-        }
-
-
-        double xoff = (ax + bx) / (2 * scale);
-        double yoff = (ay + by) / (2 * scale);
-
-
-//        const float layer_scale = layer_span / scale;
-
-        // cout << "xoff = " << xoff << ", yoff = " << yoff << endl;
-        base[0] += xoff;
-
-        // the while loops can lead to *long* pauses if base[0] comes
-        // with a bogus value.
-        // while ( base[0] > 1.0 ) { base[0] -= 1.0; }
-        // while ( base[0] < 0.0 ) { base[0] += 1.0; }
-        if ( base[0] > -10.0 && base[0] < 10.0 ) {
-            base[0] -= (int)base[0];
-        } else {
-            SG_LOG(SG_ASTRO, SG_DEBUG,
-                "Error: base = " << base[0] << "," << base[1] <<
-                " course = " << course << " dist = " << dist );
-            base[0] = 0.0;
-        }
-
-        base[1] += yoff;
-        // the while loops can lead to *long* pauses if base[0] comes
-        // with a bogus value.
-        // while ( base[1] > 1.0 ) { base[1] -= 1.0; }
-        // while ( base[1] < 0.0 ) { base[1] += 1.0; }
-        if ( base[1] > -10.0 && base[1] < 10.0 ) {
-            base[1] -= (int)base[1];
-        } else {
-            SG_LOG(SG_ASTRO, SG_DEBUG,
+        
+        if ( lon != last_pos.getLongitudeRad() || lat != last_pos.getLatitudeRad() || sp_dist != 0 ) {
+            double course = SGGeodesy::courseDeg(last_pos, pos) * SG_DEGREES_TO_RADIANS, 
+                dist = SGGeodesy::distanceM(last_pos, pos);
+
+            // if start and dest are too close together,
+            // calc_gc_course_dist() can return a course of "nan".  If
+            // this happens, lets just use the last known good course.
+            // This is a hack, and it would probably be better to make
+            // calc_gc_course_dist() more robust.
+            if ( isnan(course) ) {
+                course = last_course;
+            } else {
+                last_course = course;
+            }
+
+            // calculate cloud movement due to external forces
+            double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0;
+
+            if (dist > 0.0) {
+                ax = -cos(course) * dist;
+                ay = sin(course) * dist;
+            }
+
+            if (sp_dist > 0) {
+                bx = cos((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
+                by = sin((180.0-direction) * SGD_DEGREES_TO_RADIANS) * sp_dist;
+            }
+
+
+            double xoff = (ax + bx) / (2 * scale);
+            double yoff = (ay + by) / (2 * scale);
+
+
+    //        const float layer_scale = layer_span / scale;
+
+            // cout << "xoff = " << xoff << ", yoff = " << yoff << endl;
+            base[0] += xoff;
+
+            // the while loops can lead to *long* pauses if base[0] comes
+            // with a bogus value.
+            // while ( base[0] > 1.0 ) { base[0] -= 1.0; }
+            // while ( base[0] < 0.0 ) { base[0] += 1.0; }
+            if ( base[0] > -10.0 && base[0] < 10.0 ) {
+                base[0] -= (int)base[0];
+            } else {
+                SG_LOG(SG_ASTRO, SG_DEBUG,
                     "Error: base = " << base[0] << "," << base[1] <<
                     " course = " << course << " dist = " << dist );
-            base[1] = 0.0;
-        }
-
-        // cout << "base = " << base[0] << "," << base[1] << endl;
-
-        setTextureOffset(base);
-        last_pos = pos;
+                base[0] = 0.0;
+            }
+
+            base[1] += yoff;
+            // the while loops can lead to *long* pauses if base[0] comes
+            // with a bogus value.
+            // while ( base[1] > 1.0 ) { base[1] -= 1.0; }
+            // while ( base[1] < 0.0 ) { base[1] += 1.0; }
+            if ( base[1] > -10.0 && base[1] < 10.0 ) {
+                base[1] -= (int)base[1];
+            } else {
+                SG_LOG(SG_ASTRO, SG_DEBUG,
+                        "Error: base = " << base[0] << "," << base[1] <<
+                        " course = " << course << " dist = " << dist );
+                base[1] = 0.0;
+            }
+
+            // cout << "base = " << base[0] << "," << base[1] << endl;
+
+            setTextureOffset(base);
+            last_pos = pos;
+        }
     }
 
     layer3D->reposition( p, up, lon, lat, dt, layer_asl, speed, direction);

Modified: simgear/trunk/simgear/scene/sky/cloud.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/cloud.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/cloud.hxx (original)
+++ simgear/trunk/simgear/scene/sky/cloud.hxx Sun Jul 15 09:07:01 2012
@@ -226,8 +226,6 @@
                      double dt = 0.0 );
 
     osg::Switch* getNode() { return cloud_root.get(); }
-
-    static bool enable_bump_mapping;
 
     /** return the 3D layer cloud associated with this 2D layer */
     SGCloudField *get_layer3D(void) { return layer3D; }

Modified: simgear/trunk/simgear/scene/sky/cloudfield.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/cloudfield.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/cloudfield.cxx (original)
+++ simgear/trunk/simgear/scene/sky/cloudfield.cxx Sun Jul 15 09:07:01 2012
@@ -43,7 +43,7 @@
 
 using std::vector;
 
-#include <simgear/environment/visual_enviro.hxx>
+//#include <simgear/environment/visual_enviro.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
 #include <simgear/scene/util/SGUpdateVisitor.hxx>
 #include "sky.hxx"
@@ -68,8 +68,9 @@
 double SGCloudField::timer_dt = 0.0;
 float SGCloudField::view_distance = 20000.0f;
 bool SGCloudField::wrap = true;
-float SGCloudField::RADIUS_LEVEL_1 = 20000.0f;
-float SGCloudField::RADIUS_LEVEL_2 = 5000.0f;
+float SGCloudField::RADIUS_LEVEL_1 = 5000.0f;
+float SGCloudField::RADIUS_LEVEL_2 = 2000.0f;
+float SGCloudField::MAX_CLOUD_DEPTH = 2000.0f;
 
 SGVec3f SGCloudField::view_vec, SGCloudField::view_X, SGCloudField::view_Y;
 
@@ -81,7 +82,9 @@
     if (placed_root->getNumChildren() == 0) return false;
 
     SGVec3<double> cart;
-    SGGeodesy::SGGeodToCart(SGGeod::fromRadFt(lon, lat, 0.0f), cart);
+    SGGeod new_pos = SGGeod::fromRadFt(lon, lat, 0.0f);
+                            
+    SGGeodesy::SGGeodToCart(new_pos, cart);
     osg::Vec3f osg_pos = toOsg(cart);
     osg::Quat orient = toOsg(SGQuatd::fromLonLatRad(lon, lat) * SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0)));
     
@@ -93,8 +96,6 @@
     osg::Vec3f wind = osg::Vec3f(-cos((direction + 180)* SGD_DEGREES_TO_RADIANS) * speed * dt,
                                  sin((direction + 180)* SGD_DEGREES_TO_RADIANS) * speed * dt,
                                  0.0f);
-    //cout << "Wind: " << direction << "@" << speed << "\n";
-    
     osg::Vec3f windosg = field_transform->getAttitude() * wind;
     field_transform->setPosition(field_transform->getPosition() + windosg);
     
@@ -108,39 +109,40 @@
         field_transform->setPosition(osg_pos);
         field_transform->setAttitude(orient);
         old_pos = osg_pos;
-    } else {
+    } else {        
+        osg::Quat fta =  field_transform->getAttitude();
+        osg::Quat ftainv = field_transform->getAttitude().inverse();
+        
         // delta is the vector from the old position to the new position in cloud-coords
-        osg::Vec3f delta = field_transform->getAttitude().inverse() * (osg_pos - old_pos);
-        //cout << "Delta: " << delta.length() << "\n";
-
-        for (unsigned int i = 0; i < placed_root->getNumChildren(); i++) {
-            osg::ref_ptr<osg::LOD> lodnode1 = (osg::LOD*) placed_root->getChild(i);
-            osg::Vec3f v = delta - lodnode1->getCenter();
-
-            if ((v.x() < -0.5*fieldSize) ||
-                (v.x() >  0.5*fieldSize) ||
-                (v.y() < -0.5*fieldSize) ||
-                (v.y() >  0.5*fieldSize)   )  {
-                //cout << "V: " << v.x() << ", " << v.y() << "\n";
-
-                osg::Vec3f shift = osg::Vec3f(0.0f, 0.0f, 0.0f);
-                if (v.x() > 0.5*fieldSize) { shift += osg::Vec3f(fieldSize, 0.0f, 0.0f); }
-                if (v.x() < -0.5*fieldSize) { shift -= osg::Vec3f(fieldSize, 0.0f, 0.0f); }
-
-                if (v.y() > 0.5*fieldSize) { shift += osg::Vec3f(0.0f, fieldSize, 0.0f); }
-                if (v.y() < -0.5*fieldSize) { shift -= osg::Vec3f(0.0f, fieldSize, 0.0f); }
-
-                //cout << "Shift: " << shift.x() << ", " << shift.y() << "\n\n";
-
-                for (unsigned int j = 0; j < lodnode1->getNumChildren(); j++) {
-                    osg::ref_ptr<osg::LOD> lodnode2 = (osg::LOD*) lodnode1->getChild(j);
-                    for (unsigned int k = 0; k < lodnode2->getNumChildren(); k++) {
-                        osg::ref_ptr<osg::PositionAttitudeTransform> pat =(osg::PositionAttitudeTransform*) lodnode2->getChild(k);
-                        pat->setPosition(pat->getPosition() + shift);
-                    }
-                }
+        // osg::Vec3f delta = ftainv * (osg_pos - old_pos);
+        old_pos = osg_pos;
+                
+        // Check if any of the clouds should be moved.
+        for(CloudHash::const_iterator itr = cloud_hash.begin(), end = cloud_hash.end();
+            itr != end;
+            ++itr) {
+              
+             osg::ref_ptr<osg::PositionAttitudeTransform> pat = itr->second;
+             osg::Vec3f currpos = field_transform->getPosition() + fta * pat->getPosition();
+                                      
+             // Determine the vector from the new position to the cloud in cloud-space.
+             osg::Vec3f w =  ftainv * (currpos - toOsg(cart));               
+              
+             // Determine a course if required. Note that this involves some axis translation.
+             float x = 0.0;
+             float y = 0.0;
+             if (w.x() >  0.6*fieldSize) { y =  fieldSize; }
+             if (w.x() < -0.6*fieldSize) { y = -fieldSize; }
+             if (w.y() >  0.6*fieldSize) { x = -fieldSize; }
+             if (w.y() < -0.6*fieldSize) { x =  fieldSize; }
+              
+             if ((x != 0.0) || (y != 0.0)) {
+                 removeCloudFromTree(pat);
+                 SGGeod p = SGGeod::fromCart(toSG(field_transform->getPosition() + 
+                                                  fta * pat->getPosition()));
+                 addCloudToTree(pat, p, x, y);                
             }
-        }
+        }        
     }
     
     // Render the clouds in order from farthest away layer to nearest one.
@@ -185,9 +187,10 @@
     for (unsigned int i = 0; i < placed_root->getNumChildren(); i++) {
         osg::ref_ptr<osg::LOD> lodnode1 = (osg::LOD*) placed_root->getChild(i);
         for (unsigned int j = 0; j < lodnode1->getNumChildren(); j++) {
+            lodnode1->setRange(j, 0.0f, view_distance + RADIUS_LEVEL_1 + RADIUS_LEVEL_2 + MAX_CLOUD_DEPTH);
             osg::ref_ptr<osg::LOD> lodnode2 = (osg::LOD*) lodnode1->getChild(j);
             for (unsigned int k = 0; k < lodnode2->getNumChildren(); k++) {
-                lodnode2->setRange(k, 0.0f, view_distance);
+                lodnode2->setRange(k, 0.0f, view_distance + MAX_CLOUD_DEPTH);
             }
         }
     }
@@ -229,28 +232,58 @@
 
 void SGCloudField::addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform,
                                   float lon, float lat, float alt, float x, float y) {
+    
+    // Get the base position
+    SGGeod loc = SGGeod::fromDegFt(lon, lat, alt);
+    addCloudToTree(transform, loc, x, y);      
+}
+
+
+void SGCloudField::addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform,
+                                  SGGeod loc, float x, float y) {
+        
+    float alt = loc.getElevationFt();
+    // Determine any shift by x/y
+    if ((x != 0.0f) || (y != 0.0f)) {
+        double crs = 90.0 - SG_RADIANS_TO_DEGREES * atan2(y, x); 
+        double dst = sqrt(x*x + y*y);
+        double endcrs;
+        
+        SGGeod base_pos = SGGeod::fromGeodFt(loc, 0.0f);            
+        SGGeodesy::direct(base_pos, crs, dst, loc, endcrs);
+    }
+    
+    // The direct call provides the position at 0 alt, so adjust as required.      
+    loc.setElevationFt(alt);    
+    addCloudToTree(transform, loc);    
+}
+        
+        
+void SGCloudField::addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform, SGGeod loc) {        
     // Work out where this cloud should go in OSG coordinates.
     SGVec3<double> cart;
-    SGGeodesy::SGGeodToCart(SGGeod::fromDegFt(lon, lat, alt), cart);
-
-    // Convert to the scenegraph orientation where we just rotate around
-    // the y axis 180 degrees.
-    osg::Quat orient = toOsg(SGQuatd::fromLonLatDeg(lon, lat) * SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0)));
-    osg::Vec3f pos = toOsg(cart) + orient * osg::Vec3f(x, y, 0.0f);
+    SGGeodesy::SGGeodToCart(loc, cart);
+    osg::Vec3f pos = toOsg(cart);
+
 
     if (old_pos == osg::Vec3f(0.0f, 0.0f, 0.0f)) {
-        // First se tup.
+        // First setup.
         SGVec3<double> fieldcenter;
-        SGGeodesy::SGGeodToCart(SGGeod::fromDegFt(lon, lat, 0.0f), fieldcenter);
-
-        field_transform->setPosition(toOsg(fieldcenter));
+        SGGeodesy::SGGeodToCart(SGGeod::fromDegFt(loc.getLongitudeDeg(), loc.getLatitudeDeg(), 0.0f), fieldcenter);
+        // Convert to the scenegraph orientation where we just rotate around
+        // the y axis 180 degrees.
+        osg::Quat orient = toOsg(SGQuatd::fromLonLatDeg(loc.getLongitudeDeg(), loc.getLatitudeDeg()) * SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0)));
+        
+        osg::Vec3f osg_pos = toOsg(fieldcenter);            
+        
+        field_transform->setPosition(osg_pos);
         field_transform->setAttitude(orient);
-        old_pos = toOsg(fieldcenter);
-}
-
+        old_pos = osg_pos;
+    }
+    
+    // Convert position to cloud-coordinates
     pos = pos - field_transform->getPosition();
-
-    pos = orient.inverse() * pos;
+    pos = field_transform->getAttitude().inverse() * pos;    
 
     // We have a two level dynamic quad tree which the cloud will be added
     // to. If there are no appropriate nodes in the quad tree, they are
@@ -263,16 +296,14 @@
         lodnode1 = (osg::LOD*) placed_root->getChild(i);
         if ((lodnode1->getCenter() - pos).length2() < RADIUS_LEVEL_1*RADIUS_LEVEL_1) {
             // New cloud is within RADIUS_LEVEL_1 of the center of the LOD node.
-            //cout << "Adding cloud to existing LoD level 1 node. Distance:" << (lodnode1->getCenter() - pos).length() << "\n";
             found = true;
-                        }
-                    }
+        }
+    }
 
     if (!found) {
         lodnode1 = new osg::LOD();
         placed_root->addChild(lodnode1.get());
-        //cout << "Adding cloud to new LoD node\n";
-                }
+    }
 
     // Now check if there is a second level LOD node at an appropriate distance
     found = false;
@@ -281,20 +312,18 @@
         lodnode = (osg::LOD*) lodnode1->getChild(j);
         if ((lodnode->getCenter() - pos).length2() < RADIUS_LEVEL_2*RADIUS_LEVEL_2) {
             // We've found the right leaf LOD node
-            //cout << "Found existing LOD leaf node. Distance:"<< (lodnode->getCenter() - pos).length() << "\n";
             found = true;
-            }
-        }
+        }
+    }
 
     if (!found) {
         // No suitable leave node was found, so we need to add one.
         lodnode = new osg::LOD();
-        lodnode1->addChild(lodnode, 0.0f, 4*RADIUS_LEVEL_1);
-        //cout << "Adding cloud to new LoD node\n";
-}
+        lodnode1->addChild(lodnode, 0.0f, view_distance + RADIUS_LEVEL_1 + RADIUS_LEVEL_2 + MAX_CLOUD_DEPTH);
+    }
 
     transform->setPosition(pos);
-    lodnode->addChild(transform.get(), 0.0f, view_distance);
+    lodnode->addChild(transform.get(), 0.0f, view_distance + MAX_CLOUD_DEPTH);
 
     lodnode->dirtyBound();
     lodnode1->dirtyBound();

Modified: simgear/trunk/simgear/scene/sky/cloudfield.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/cloudfield.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/cloudfield.hxx (original)
+++ simgear/trunk/simgear/scene/sky/cloudfield.hxx Sun Jul 15 09:07:01 2012
@@ -70,32 +70,38 @@
 		bool		visible;
 	};
 
-        float Rnd(float);
+  float Rnd(float);
         
   // Radius of the LoD nodes for the dynamic quadtrees.
   static float RADIUS_LEVEL_1;
   static float RADIUS_LEVEL_2;
 
+  // Theoretical maximum cloud depth, used for fudging the LoD
+  // ranges to ensure that clouds become visible at maximum range
+  static float MAX_CLOUD_DEPTH;
+
 	// this is a relative position only, with that we can move all clouds at once
 	SGVec3f relative_position;
 
-        osg::ref_ptr<osg::Group> field_root;
+  osg::ref_ptr<osg::Group> field_root;
   osg::ref_ptr<osg::Group> placed_root;
   osg::ref_ptr<osg::PositionAttitudeTransform> field_transform;
-        osg::ref_ptr<osg::PositionAttitudeTransform> altitude_transform;
-        osg::ref_ptr<osg::LOD> field_lod;
+  osg::ref_ptr<osg::PositionAttitudeTransform> altitude_transform;
+  osg::ref_ptr<osg::LOD> field_lod;
 
   osg::Vec3f old_pos;
   CloudHash cloud_hash;
 
-        struct CloudFog : public simgear::Singleton<CloudFog>
-        {
-                CloudFog();
-                osg::ref_ptr<osg::Fog> fog;
-        };
+  struct CloudFog : public simgear::Singleton<CloudFog>
+  {
+    CloudFog();
+    osg::ref_ptr<osg::Fog> fog;
+  };
 
   void removeCloudFromTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform);
   void addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform, float lon, float lat, float alt, float x, float y);
+  void addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform, SGGeod loc, float x, float y);
+  void addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> transform, SGGeod loc);
   void applyVisRangeAndCoverage(void);
 
 public:
@@ -122,41 +128,44 @@
 
 
   /**
-        * reposition the cloud layer at the specified origin and
-        * orientation.
-        * @param p position vector
-        * @param up the local up vector
-        * @param lon specifies a rotation about the Z axis
-        * @param lat specifies a rotation about the new Y axis
-        * @param dt the time elapsed since the last call
-        * @param asl altitude of the layer
-  * @param speed of cloud layer movement (due to wind)
-  * @param direction of cloud layer movement (due to wind)
-        */
-        bool reposition( const SGVec3f& p, const SGVec3f& up,
-                  double lon, double lat, double dt, int asl, float speed, float direction);
+    * reposition the cloud layer at the specified origin and
+    * orientation.
+    * @param p position vector
+    * @param up the local up vector
+    * @param lon specifies a rotation about the Z axis
+    * @param lat specifies a rotation about the new Y axis
+    * @param dt the time elapsed since the last call
+    * @param asl altitude of the layer
+    * @param speed of cloud layer movement (due to wind)
+    * @param direction of cloud layer movement (due to wind)
+    */
+  bool reposition( const SGVec3f& p, const SGVec3f& up,
+            double lon, double lat, double dt, int asl, float speed, float direction);
 
-        osg::Group* getNode() { return field_root.get(); }
+  osg::Group* getNode() { return field_root.get(); }
 
-	// visibility distance for clouds in meters
-	static float CloudVis;
+  // visibility distance for clouds in meters
+  static float CloudVis;
 
-	static SGVec3f view_vec, view_X, view_Y;
+  static SGVec3f view_vec, view_X, view_Y;
 
-        static float view_distance;
-        static double timer_dt;
-	static float fieldSize;
-	static bool wrap;
+  static float view_distance;
+  static double timer_dt;
+  static float fieldSize;
+  static bool wrap;
 
-        static float getVisRange(void) { return view_distance; }
-        static void setVisRange(float d) { view_distance = d; }
-        void applyVisRange(void);
-        
-        static osg::Fog* getFog()
-        {
-                return CloudFog::instance()->fog.get();
-        }
-        static void updateFog(double visibility, const osg::Vec4f& color);
+  static bool getWrap(void) { return wrap; }
+  static void setWrap(bool w) { wrap = w; }
+
+  static float getVisRange(void) { return view_distance; }
+  static void setVisRange(float d) { view_distance = d; }
+  void applyVisRange(void);
+
+  static osg::Fog* getFog()
+  {
+          return CloudFog::instance()->fog.get();
+  }
+  static void updateFog(double visibility, const osg::Vec4f& color);
 };
 
 #endif // _CLOUDFIELD_HXX

Modified: simgear/trunk/simgear/scene/sky/dome.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/dome.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/dome.cxx (original)
+++ simgear/trunk/simgear/scene/sky/dome.cxx Sun Jul 15 09:07:01 2012
@@ -294,7 +294,7 @@
     const double saif = sun_angle/SG_PI;
     static const SGVec3f blueShift(0.8, 1.0, 1.2);
     const SGVec3f skyFogDelta = sky_color - fog_color;
-    const SGVec3f sunSkyDelta = sun_color - sky_color;
+//    const SGVec3f sunSkyDelta = sun_color - sky_color;
 
     // For now the colors of the upper two rings are linearly
     // interpolated between the zenith color and the first horizon

Modified: simgear/trunk/simgear/scene/sky/moon.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/moon.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/moon.cxx (original)
+++ simgear/trunk/simgear/scene/sky/moon.cxx Sun Jul 15 09:07:01 2012
@@ -50,7 +50,7 @@
 #include <simgear/constants.h>
 #include <simgear/screen/colors.hxx>
 #include <simgear/scene/model/model.hxx>
-#include <simgear/misc/PathOptions.hxx>
+#include <simgear/scene/util/PathOptions.hxx>
 
 #include "sphere.hxx"
 #include "moon.hxx"

Modified: simgear/trunk/simgear/scene/sky/newcloud.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/newcloud.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/newcloud.cxx (original)
+++ simgear/trunk/simgear/scene/sky/newcloud.cxx Sun Jul 15 09:07:01 2012
@@ -42,10 +42,10 @@
 
 #include <simgear/math/sg_random.h>
 #include <simgear/misc/sg_path.hxx>
-#include <simgear/misc/PathOptions.hxx>
+#include <simgear/scene/util/PathOptions.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/scene/model/model.hxx>
-#include <simgear/scene/model/SGReaderWriterXMLOptions.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/scene/util/StateAttributeFactory.hxx>
 #include <simgear/scene/util/SGUpdateVisitor.hxx>
 
@@ -60,6 +60,8 @@
 
 using namespace simgear;
 using namespace osg;
+using namespace std;
+
 
 namespace
 {
@@ -67,22 +69,36 @@
 EffectMap effectMap;
 }
 
-double SGNewCloud::sprite_density = 1.0;
+float SGNewCloud::sprite_density = 1.0;
 
 SGNewCloud::SGNewCloud(const SGPath &texture_root, const SGPropertyNode *cld_def)
 {
-    min_width = cld_def->getDoubleValue("min-cloud-width-m", 500.0);
-    max_width = cld_def->getDoubleValue("max-cloud-width-m", 1000.0);
-    min_height = cld_def->getDoubleValue("min-cloud-height-m", min_width);
-    max_height = cld_def->getDoubleValue("max-cloud-height-m", max_width);
-    min_sprite_width = cld_def->getDoubleValue("min-sprite-width-m", 200.0);
-    max_sprite_width = cld_def->getDoubleValue("max-sprite-width-m", min_sprite_width);
-    min_sprite_height = cld_def->getDoubleValue("min-sprite-height-m", min_sprite_width);
-    max_sprite_height = cld_def->getDoubleValue("max-sprite-height-m", max_sprite_width);
+    min_width = cld_def->getFloatValue("min-cloud-width-m", 500.0);
+    max_width = cld_def->getFloatValue("max-cloud-width-m", min_width*2);
+    min_height = cld_def->getFloatValue("min-cloud-height-m", 400.0);
+    max_height = cld_def->getFloatValue("max-cloud-height-m", min_height*2);
+    min_sprite_width = cld_def->getFloatValue("min-sprite-width-m", 200.0);
+    max_sprite_width = cld_def->getFloatValue("max-sprite-width-m", min_sprite_width*1.5);
+    min_sprite_height = cld_def->getFloatValue("min-sprite-height-m", 150);
+    max_sprite_height = cld_def->getFloatValue("max-sprite-height-m", min_sprite_height*1.5);
     num_sprites = cld_def->getIntValue("num-sprites", 20);
     num_textures_x = cld_def->getIntValue("num-textures-x", 4);
     num_textures_y = cld_def->getIntValue("num-textures-y", 4);
-    bottom_shade = cld_def->getDoubleValue("bottom-shade", 1.0);
+    height_map_texture = cld_def->getBoolValue("height-map-texture", false);
+    
+    min_bottom_lighting_factor = cld_def->getFloatValue("min-bottom-lighting-factor", 1.0);
+    max_bottom_lighting_factor = cld_def->getFloatValue("max-bottom-lighting-factor", min(min_bottom_lighting_factor  + 0.1, 1.0));
+    
+    min_middle_lighting_factor = cld_def->getFloatValue("min-middle-lighting-factor", 1.0);
+    max_middle_lighting_factor = cld_def->getFloatValue("max-middle-lighting-factor", min(min_middle_lighting_factor  + 0.1, 1.0));
+
+    min_top_lighting_factor = cld_def->getFloatValue("min-top-lighting-factor", 1.0);
+    max_top_lighting_factor = cld_def->getFloatValue("max-top-lighting-factor", min(min_top_lighting_factor  + 0.1, 1.0));
+
+    min_shade_lighting_factor = cld_def->getFloatValue("min-shade-lighting-factor", 0.5);
+    max_shade_lighting_factor = cld_def->getFloatValue("max-shade-lighting-factor", min(min_shade_lighting_factor  + 0.1, 1.0));
+    
+    zscale = cld_def->getFloatValue("z-scale", 1.0);
     texture = cld_def->getStringValue("texture", "cl_cumulus.png");
 
     // Create a new Effect for the texture, if required.
@@ -96,8 +112,8 @@
                  texture);
         ref_ptr<osgDB::ReaderWriter::Options> options
             = makeOptionsFromPath(texture_root);
-        ref_ptr<SGReaderWriterXMLOptions> sgOptions
-            = new SGReaderWriterXMLOptions(*options.get());
+        ref_ptr<SGReaderWriterOptions> sgOptions
+            = new SGReaderWriterOptions(*options.get());
         if ((effect = makeEffect(pcloudEffect, true, sgOptions.get())))
             effectMap.insert(EffectMap::value_type(texture, effect));
     } else {
@@ -119,11 +135,12 @@
     osg::Vec2Array& t = *(new osg::Vec2Array(4));
     
     float cw = w*0.5f;
-
-    v[0].set(0.0f, -cw, 0.0f);
-    v[1].set(0.0f,  cw, 0.0f);
-    v[2].set(0.0f,  cw, h);
-    v[3].set(0.0f, -cw, h);
+    float ch = h*0.5f;
+    
+    v[0].set(0.0f, -cw, -ch);
+    v[1].set(0.0f,  cw, -ch);
+    v[2].set(0.0f,  cw, ch);
+    v[3].set(0.0f, -cw, ch);
     
     // The texture coordinate range is not the
     // entire coordinate space - as the texture
@@ -165,46 +182,68 @@
     
     osg::ref_ptr<EffectGeode> geode = new EffectGeode;
         
-    CloudShaderGeometry* sg = new CloudShaderGeometry(num_textures_x, num_textures_y, max_width, max_height);
-    
     // Determine how big this specific cloud instance is. Note that we subtract
     // the sprite size because the width/height is used to define the limits of
     // the center of the sprites, not their edges.
     float width = min_width + sg_random() * (max_width - min_width) - min_sprite_width;
     float height = min_height + sg_random() * (max_height - min_height) - min_sprite_height;
     
+    if (width  < 0.0) { width  = 0.0; }
+    if (height < 0.0) { height = 0.0; }
+    
+    // Determine appropriate shading factors
+    float top_factor = min_top_lighting_factor + sg_random() * (max_top_lighting_factor - min_top_lighting_factor);
+    float middle_factor = min_middle_lighting_factor + sg_random() * (max_middle_lighting_factor - min_middle_lighting_factor);
+    float bottom_factor = min_bottom_lighting_factor + sg_random() * (max_bottom_lighting_factor - min_bottom_lighting_factor);
+    float shade_factor = min_shade_lighting_factor + sg_random() * (max_shade_lighting_factor - min_shade_lighting_factor);
+    
+    //printf("Cloud: %2f, %2f, %2f, %2f\n", top_factor, middle_factor, bottom_factor, shade_factor); 
+    
+    CloudShaderGeometry* sg = new CloudShaderGeometry(num_textures_x, 
+                                                      num_textures_y, 
+                                                      max_width + max_sprite_width, 
+                                                      max_height + max_sprite_height, 
+                                                      top_factor,
+                                                      middle_factor,
+                                                      bottom_factor,
+                                                      shade_factor,
+                                                      height,
+                                                      zscale);
+        
     // Determine the cull distance. This is used to remove sprites that are too close together.
     // The value is squared as we use vector calculations.
     float cull_distance_squared = min_sprite_height * min_sprite_height * 0.1f;
     
     // The number of sprites we actually use is a function of the (user-controlled) density
-    int n_sprites = num_sprites * sprite_density * (0.5 + sg_random());
+    int n_sprites = num_sprites * sprite_density * (0.5f + sg_random());
     
     for (int i = 0; i < n_sprites; i++)
     {
         // Determine the position of the sprite. Rather than being completely random,
         // we place them on the surface of a distorted sphere. However, we place
         // the first sprite in the center of the sphere (and at maximum size) to
-	// ensure good coverage and reduce the chance of there being "holes" in our
+	      // ensure good coverage and reduce the chance of there being "holes" in the
+	      // middle of our cloud. Also note that (0,0,0) defines the _bottom_ of the
+	      // cloud, not the middle. 
 
         float x, y, z;
 
         if (i == 0) {
             x = 0;
             y = 0;
-            z = 0;
+            z = height * 0.5;
         } else {
-            double theta = sg_random() * SGD_2PI;
-            double elev  = sg_random() * SGD_PI;
+            float theta = sg_random() * SGD_2PI;
+            float elev  = sg_random() * SGD_PI;
             x = width * cos(theta) * 0.5f * sin(elev);
             y = width * sin(theta) * 0.5f * sin(elev);
-            z = height * cos(elev) * 0.5f;
+            z = height * cos(elev) * 0.5f + height * 0.5f;
         }
         
         // Determine the height and width as scaling factors on the minimum size (used to create the quad).
         float sprite_width = 1.0f + sg_random() * (max_sprite_width - min_sprite_width) / min_sprite_width;
         float sprite_height = 1.0f + sg_random() * (max_sprite_height - min_sprite_height) / min_sprite_height;
-
+        
         // Sprites are never taller than square.
         if (sprite_height * min_sprite_height > sprite_width * min_sprite_width)
         {
@@ -216,25 +255,36 @@
             sprite_width = 1.0f + (max_sprite_width - min_sprite_width) / min_sprite_width;
             sprite_height = 1.0f + (max_sprite_height - min_sprite_height) / min_sprite_height;
         }
+        
+        // If the center of the sprite is less than half the sprite heightthe sprite will extend 
+        // below the bottom of the cloud and must be shifted upwards. This is particularly important 
+        // for cumulus clouds which have a very well defined base.
+        if (z < 0.5f * sprite_height * min_sprite_height)
+        {
+            z = 0.5f * sprite_height * min_sprite_height;          
+        }        
 
         // Determine the sprite texture indexes.
         int index_x = (int) floor(sg_random() * num_textures_x);
-        if (index_x == num_textures_x) { index_x--; }
-
-        // The y index depends on the positing of the sprite within the cloud.
-        // This allows cloud designers to have particular sprites for the base
-        // and tops of the cloud.
-        int index_y = (int) floor((z / height + 0.5f) * num_textures_y);
-        if (index_y == num_textures_y) { index_y--; }
+        if (index_x >= num_textures_x) { index_x = num_textures_x - 1; }
+                
+        int index_y = (int) floor(sg_random() * num_textures_y);
+        
+        if (height_map_texture) {
+          // The y index depends on the position of the sprite within the cloud.
+          // This allows cloud designers to have particular sprites for the base
+          // and tops of the cloud.
+          index_y = (int) floor((z / height) * num_textures_y);
+        }
+        
+        if (index_y >= num_textures_y) { index_y = num_textures_y - 1; }
         
         sg->addSprite(SGVec3f(x, y, z), 
-                    index_x, 
-                    index_y, 
-                    sprite_width, 
-                    sprite_height, 
-                    bottom_shade, 
-                    cull_distance_squared, 
-                    height * 0.5f);
+                      index_x, 
+                      index_y, 
+                      sprite_width, 
+                      sprite_height, 
+                      cull_distance_squared);
     }
     
     sg->setGeometry(quad);

Modified: simgear/trunk/simgear/scene/sky/newcloud.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/newcloud.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/newcloud.hxx (original)
+++ simgear/trunk/simgear/scene/sky/newcloud.hxx Sun Jul 15 09:07:01 2012
@@ -47,7 +47,7 @@
         // Generate a Cloud
         osg::ref_ptr<simgear::EffectGeode> genCloud ();
 
-        static double getDensity(void)
+        static float getDensity(void)
         {
             return sprite_density;
         }
@@ -61,22 +61,45 @@
 
 private:
 
-        double min_width;
-        double max_width;
-        double min_height;
-        double max_height;
-        double min_sprite_width;
-        double max_sprite_width;
-        double min_sprite_height;
-        double max_sprite_height;
-        double bottom_shade;
+        float min_width;
+        float max_width;
+        float min_height;
+        float max_height;
+        float min_sprite_width;
+        float max_sprite_width;
+        float min_sprite_height;
+        float max_sprite_height;
+        
+        // Minimum and maximum bottom, middle, top, sunny, shade lighting
+        // factors. For individual clouds we choose a bottom/middle/top
+        // shade from between each min/max value
+        float min_bottom_lighting_factor;
+        float max_bottom_lighting_factor;
+        float min_middle_lighting_factor;
+        float max_middle_lighting_factor;
+        float min_top_lighting_factor;
+        float max_top_lighting_factor;
+        float min_shade_lighting_factor;
+        float max_shade_lighting_factor;
+        
+        // The density of the cloud is the shading applied
+        // to cloud sprites on the opposite side of the cloud
+        // from the sun. For an invidual cloud instance a value
+        // between min_density and max_density is chosen.
+        float min_density;
+        float max_density;
+        
+        // zscale indicates how sprites should be scaled vertically
+        // after billboarding. 
+        float zscale;
+        bool height_map_texture;
         int num_sprites;
         int num_textures_x;
         int num_textures_y;
         string texture;
         osg::Geometry* quad;
         osg::ref_ptr<simgear::Effect> effect;
-        static double sprite_density;
+        static float sprite_density;
 
         osg::Geometry* createOrthQuad(float w, float h, int varieties_x, int varieties_y);
 

Modified: simgear/trunk/simgear/scene/sky/oursun.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/oursun.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/oursun.cxx (original)
+++ simgear/trunk/simgear/scene/sky/oursun.cxx Sun Jul 15 09:07:01 2012
@@ -42,7 +42,7 @@
 #include <osgDB/ReadFile>
 
 #include <simgear/math/SGMath.hxx>
-#include <simgear/misc/PathOptions.hxx>
+#include <simgear/scene/util/PathOptions.hxx>
 #include <simgear/screen/colors.hxx>
 #include <simgear/scene/model/model.hxx>
 #include "oursun.hxx"

Modified: simgear/trunk/simgear/scene/sky/sky.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/sky.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/sky.cxx (original)
+++ simgear/trunk/simgear/scene/sky/sky.cxx Sun Jul 15 09:07:01 2012
@@ -236,6 +236,16 @@
         cloud_layers[i]->get_layer3D()->applyVisRange();
     }
 }
+
+bool SGSky::get_3dCloudWrap() const {
+    return SGCloudField::getWrap();
+}
+
+void SGSky::set_3dCloudWrap(bool wrap)
+{
+    SGCloudField::setWrap(wrap);
+}
+
 
 void SGSky::texture_path( const string& path ) {
 	tex_path = SGPath( path );

Modified: simgear/trunk/simgear/scene/sky/sky.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/sky/sky.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/sky/sky.hxx (original)
+++ simgear/trunk/simgear/scene/sky/sky.hxx Sun Jul 15 09:07:01 2012
@@ -53,14 +53,11 @@
 #include <simgear/scene/sky/oursun.hxx>
 #include <simgear/scene/sky/stars.hxx>
 
-using std::vector;
-
-
 typedef struct {
-        SGVec3d pos;
-        SGGeod pos_geod;
-        SGQuatd ori;
-        double spin;
+    SGVec3d pos;
+    SGGeod pos_geod;
+    SGQuatd ori;
+    double spin;
 	double gst;
 	double sun_dist;
 	double moon_dist;
@@ -69,8 +66,8 @@
 
 typedef struct {
 	SGVec3f sky_color;
-        SGVec3f adj_sky_color;
-        SGVec3f fog_color;
+    SGVec3f adj_sky_color;
+    SGVec3f fog_color;
 	SGVec3f cloud_color;
 	double sun_angle, moon_angle;
 } SGSkyColor;
@@ -440,6 +437,15 @@
      */
     virtual void set_3dCloudVisRange(float vis);
 
+    /** Get 3D cloud wrapping */
+    virtual bool get_3dCloudWrap() const;
+
+    /** Set 3D cloud wrapping
+     * @param wrap whether to wrap 3D clouds
+     */
+    virtual void set_3dCloudWrap(bool wrap);
+
+
 };
 
 

Modified: simgear/trunk/simgear/scene/tgdb/SGOceanTile.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/SGOceanTile.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/SGOceanTile.cxx (original)
+++ simgear/trunk/simgear/scene/tgdb/SGOceanTile.cxx Sun Jul 15 09:07:01 2012
@@ -60,12 +60,11 @@
 // it may be superfluous for such a small mesh.
 namespace
 {
-const int lonPoints = 5;
-const int latPoints = 5;
-
 class OceanMesh {
 public:
-    OceanMesh():
+    OceanMesh(int latP, int lonP):
+        latPoints(latP),
+        lonPoints(lonP),
         geoPoints(latPoints * lonPoints + 2 * (lonPoints + latPoints)),
         geod_nodes(latPoints * lonPoints),
         vl(new osg::Vec3Array(geoPoints)),
@@ -75,11 +74,24 @@
         nlArray(*nl, lonPoints + 2, lonPoints, 1),
         tlArray(*tl, lonPoints + 2, lonPoints, 1)
     {
-    }
+        int numPoints = latPoints * lonPoints;
+        geod = new SGGeod[numPoints];
+        normals = new SGVec3f[numPoints];
+        rel = new SGVec3d[numPoints];
+    }
+    
+    ~OceanMesh()
+    {
+        delete[] geod;
+        delete[] normals;
+        delete[] rel;
+    }
+    
+    const int latPoints, lonPoints;
     const int geoPoints;
-    SGGeod geod[latPoints][lonPoints];
-    SGVec3f normals[latPoints][lonPoints];
-    SGVec3d rel[latPoints][lonPoints];
+    SGGeod* geod;
+    SGVec3f* normals;
+    SGVec3d* rel;
 
     std::vector<SGGeod> geod_nodes;
 
@@ -114,10 +126,11 @@
     for (int j = 0; j < latPoints; j++) {
         double lat = startLat + j * latInc;
         for (int i = 0; i < lonPoints; i++) {
-            geod[j][i] = SGGeod::fromDeg(startLon + i * longInc, lat);
-            SGVec3d cart = SGVec3d::fromGeod(geod[j][i]);
-            rel[j][i] = orient.transform(cart - cartCenter);
-            normals[j][i] = toVec3f(orient.transform(normalize(cart)));
+            int index = (j * lonPoints) + i;
+            geod[index] = SGGeod::fromDeg(startLon + i * longInc, lat);
+            SGVec3d cart = SGVec3d::fromGeod(geod[index]);
+            rel[index] = orient.transform(cart - cartCenter);
+            normals[index] = toVec3f(orient.transform(normalize(cart)));
         }
     }
     
@@ -130,8 +143,9 @@
     VectorArrayAdapter<int_list> rectArray(rectangle, lonPoints);
     for (int j = 0; j < latPoints; j++) {
         for (int i = 0; i < lonPoints; i++) {
-            geodNodesArray(j, i) = geod[j][i];
-            rectArray(j, i) = j * 5 + i;
+            int index = (j * lonPoints) + i;
+            geodNodesArray(j, i) = geod[index];
+            rectArray(j, i) = index;
         }
     }
     
@@ -144,8 +158,9 @@
   
     for (int j = 0; j < latPoints; j++) {
         for (int i = 0; i < lonPoints; ++i) {
-            vlArray(j, i) = toOsg(rel[j][i]);
-            nlArray(j, i) = toOsg(normals[j][i]);
+            int index = (j * lonPoints) + i;
+            vlArray(j, i) = toOsg(rel[index]);
+            nlArray(j, i) = toOsg(normals[index]);
             tlArray(j, i) = toOsg(texsArray(j, i));
         }
     }
@@ -259,7 +274,7 @@
 }
 }
 
-osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib)
+osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib, int latPoints, int lonPoints)
 {
     Effect *effect = 0;
 
@@ -277,7 +292,7 @@
     } else {
         SG_LOG( SG_TERRAIN, SG_ALERT, "Ack! unknown use material name = Ocean");
     }
-    OceanMesh grid;
+    OceanMesh grid(latPoints, lonPoints);
     // Calculate center point
     SGVec3d cartCenter = SGVec3d::fromGeod(b.get_center());
     SGGeod geodPos = SGGeod::fromCart(cartCenter);

Modified: simgear/trunk/simgear/scene/tgdb/SGOceanTile.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/SGOceanTile.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/SGOceanTile.hxx (original)
+++ simgear/trunk/simgear/scene/tgdb/SGOceanTile.hxx Sun Jul 15 09:07:01 2012
@@ -28,6 +28,6 @@
 class SGMaterialLib;
 
 // Generate an ocean tile
-osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib);
+osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib, int latPoints = 5, int lonPoints = 5);
 
 #endif // _SG_OBJ_HXX

Modified: simgear/trunk/simgear/scene/tgdb/SGReaderWriterBTG.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/SGReaderWriterBTG.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/SGReaderWriterBTG.cxx (original)
+++ simgear/trunk/simgear/scene/tgdb/SGReaderWriterBTG.cxx Sun Jul 15 09:07:01 2012
@@ -15,12 +15,17 @@
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
 #include <osgDB/FileNameUtils>
 #include <osgDB/Registry>
 
 #include <simgear/scene/model/ModelRegistry.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
+#include <simgear/math/SGMath.hxx>
 
-#include "SGReaderWriterBTGOptions.hxx"
 #include "SGReaderWriterBTG.hxx"
 #include "obj.hxx"
 
@@ -29,6 +34,7 @@
 SGReaderWriterBTG::SGReaderWriterBTG()
 {
     supportsExtension("btg", "SimGear btg database format");
+    // supportsExtension("btg.gz", "SimGear btg database format");
 }
 
 SGReaderWriterBTG::~SGReaderWriterBTG()
@@ -43,8 +49,8 @@
 bool
 SGReaderWriterBTG::acceptsExtension(const std::string& extension) const
 {
-    std::string lowercase_ext = osgDB::convertToLowerCase(extension);
-    if (lowercase_ext == "gz")
+    // trick the osg extensions match algorithm to accept btg.gz files.
+    if (osgDB::convertToLowerCase(extension) == "gz")
         return true;
     return osgDB::ReaderWriter::acceptsExtension(extension);
 }
@@ -54,18 +60,24 @@
                             const osgDB::ReaderWriter::Options* options) const
 {
     SGMaterialLib* matlib = 0;
-    bool calcLights = false;
     bool useRandomObjects = false;
     bool useRandomVegetation = false;
-    const SGReaderWriterBTGOptions* btgOptions
-        = dynamic_cast<const SGReaderWriterBTGOptions*>(options);
-    if (btgOptions) {
-        matlib = btgOptions->getMatlib();
-        calcLights = btgOptions->getCalcLights();
-        useRandomObjects = btgOptions->getUseRandomObjects();
-        useRandomVegetation = btgOptions->getUseRandomVegetation();
+    const SGReaderWriterOptions* sgOptions;
+    sgOptions = dynamic_cast<const SGReaderWriterOptions*>(options);
+    if (sgOptions) {
+        matlib = sgOptions->getMaterialLib();
+        SGPropertyNode* propertyNode = sgOptions->getPropertyNode().get();
+        if (propertyNode) {
+            useRandomObjects
+                = propertyNode->getBoolValue("/sim/rendering/random-objects",
+                                             useRandomObjects);
+            useRandomVegetation
+                = propertyNode->getBoolValue("/sim/rendering/random-vegetation",
+                                             useRandomVegetation);
+        }
     }
-    osg::Node* result = SGLoadBTG(fileName, matlib, calcLights,
+
+    osg::Node* result = SGLoadBTG(fileName, matlib,
                                   useRandomObjects,
                                   useRandomVegetation);
     if (result)

Modified: simgear/trunk/simgear/scene/tgdb/TileEntry.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/TileEntry.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/TileEntry.cxx (original)
+++ simgear/trunk/simgear/scene/tgdb/TileEntry.cxx Sun Jul 15 09:07:01 2012
@@ -49,8 +49,9 @@
 #include <simgear/scene/model/ModelRegistry.hxx>
 #include <simgear/scene/tgdb/apt_signs.hxx>
 #include <simgear/scene/tgdb/obj.hxx>
-#include <simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx>
-
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
+
+#include "ReaderWriterSPT.hxx"
 #include "ReaderWriterSTG.hxx"
 #include "TileEntry.hxx"
 
@@ -62,6 +63,9 @@
 namespace {
 osgDB::RegisterReaderWriterProxy<ReaderWriterSTG> g_readerWriterSTGProxy;
 ModelRegistryCallbackProxy<LoadOnlyCallback> g_stgCallbackProxy("stg");
+
+osgDB::RegisterReaderWriterProxy<ReaderWriterSPT> g_readerWriterSPTProxy;
+ModelRegistryCallbackProxy<LoadOnlyCallback> g_sptCallbackProxy("spt");
 }
 
 
@@ -196,8 +200,12 @@
     osgDB::FilePathList path_list=options->getDatabasePathList();
     // Make sure we find the original filename here...
     std::string filePath = osgDB::getFilePath(fileName);
-    if (!filePath.empty())
-        path_list.push_front(filePath);
+    if (!filePath.empty()) {
+        SGPath p(filePath);
+        p.append("..");
+        p.append("..");
+        path_list.push_front(p.str());
+    }
 
     // scan and parse all files and store information
     for (unsigned int i = 0; i < path_list.size(); i++) {
@@ -288,27 +296,26 @@
         }
     }
 
-    const SGReaderWriterBTGOptions* btgOpt;
-    btgOpt = dynamic_cast<const SGReaderWriterBTGOptions *>(options);
-    osg::ref_ptr<SGReaderWriterBTGOptions> opt;
+    const SGReaderWriterOptions* btgOpt;
+    btgOpt = dynamic_cast<const SGReaderWriterOptions*>(options);
+    osg::ref_ptr<SGReaderWriterOptions> opt;
     if (btgOpt)
-        opt = new SGReaderWriterBTGOptions(*btgOpt);
+        opt = new SGReaderWriterOptions(*btgOpt);
     else
-        opt = new SGReaderWriterBTGOptions;
+        opt = new SGReaderWriterOptions;
 
     // obj_load() will generate ground lighting for us ...
     osg::Group* new_tile = new osg::Group;
 
     if (found_tile_base) {
         // load tile if found ...
-        opt->setCalcLights(true);
         obj_load( object_base.str(), new_tile, true, opt.get());
 
     } else {
         // ... or generate an ocean tile on the fly
         SG_LOG(SG_TERRAIN, SG_INFO, "  Generating ocean tile");
         if ( !SGGenTile( path_list[0], tile_bucket,
-                        opt->getMatlib(), new_tile ) ) {
+                        opt->getMaterialLib(), new_tile ) ) {
             SG_LOG( SG_TERRAIN, SG_ALERT,
                     "Warning: failed to generate ocean tile!" );
         }
@@ -322,7 +329,6 @@
         if (obj->type == OBJECT) {
             SGPath custom_path = obj->path;
             custom_path.append( obj->name );
-            opt->setCalcLights(true);
             obj_load( custom_path.str(), new_tile, false, opt.get());
 
         } else if (obj->type == OBJECT_SHARED || obj->type == OBJECT_STATIC) {
@@ -366,9 +372,9 @@
 
             osg::Node *custom_obj = 0;
             if (obj->type == OBJECT_SIGN)
-                custom_obj = SGMakeSign(opt->getMatlib(), custom_path.str(), obj->name);
+                custom_obj = SGMakeSign(opt->getMaterialLib(), custom_path.str(), obj->name);
             else
-                custom_obj = SGMakeRunwaySign(opt->getMatlib(), custom_path.str(), obj->name);
+                custom_obj = SGMakeRunwaySign(opt->getMaterialLib(), custom_path.str(), obj->name);
 
             // wire the pieces together
             if ( custom_obj != NULL ) {

Modified: simgear/trunk/simgear/scene/tgdb/TreeBin.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/TreeBin.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/TreeBin.cxx (original)
+++ simgear/trunk/simgear/scene/tgdb/TreeBin.cxx Sun Jul 15 09:07:01 2012
@@ -54,6 +54,7 @@
 #include "TreeBin.hxx"
 
 #define SG_TREE_QUAD_TREE_DEPTH 3
+#define SG_TREE_FADE_OUT_LEVELS 10
 
 using namespace osg;
 
@@ -230,9 +231,15 @@
     LOD* operator() () const
     {
         LOD* result = new LOD;
-        EffectGeode* geode = createTreeGeode(_width, _height, _varieties);
-        geode->setEffect(_effect.get());
-        result->addChild(geode, 0, _range);
+        
+        // Create a series of LOD nodes so trees cover decreases slightly
+        // gradually with distance from _range to 2*_range
+        for (float i = 0.0; i < SG_TREE_FADE_OUT_LEVELS; i++)
+        {        
+            EffectGeode* geode = createTreeGeode(_width, _height, _varieties);
+            geode->setEffect(_effect.get());
+            result->addChild(geode, 0, _range * (1.0 + i / (SG_TREE_FADE_OUT_LEVELS - 1.0)));
+        }
         return result;
     }
     float _range;
@@ -246,7 +253,7 @@
 {
     void operator() (LOD* lod, const TreeBin::Tree& tree) const
     {
-        Geode* geode = static_cast<Geode*>(lod->getChild(0));
+        Geode* geode = static_cast<Geode*>(lod->getChild(int(tree.position.x() * 10.0f) % lod->getNumChildren()));
         addTreeToLeafGeode(geode, tree.position);
     }
 };
@@ -278,48 +285,55 @@
 // forest into the local Z-up coordinate system we can reuse the
 // primitive tree geometry for all the forests of the same type.
 
-osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform)
+osg::Group* createForest(SGTreeBinList& forestList, const osg::Matrix& transform)
 {
     Matrix transInv = Matrix::inverse(transform);
     static Matrix ident;
     // Set up some shared structures.
     ref_ptr<Group> group;
-
-    Effect* effect = 0;
-    EffectMap::iterator iter = treeEffectMap.find(forest.texture);
-    if (iter == treeEffectMap.end()) {
-        SGPropertyNode_ptr effectProp = new SGPropertyNode;
-        makeChild(effectProp, "inherits-from")->setStringValue("Effects/tree");
-        SGPropertyNode* params = makeChild(effectProp, "parameters");
-        // emphasize n = 0
-        params->getChild("texture", 0, true)->getChild("image", 0, true)
-            ->setStringValue(forest.texture);
-        effect = makeEffect(effectProp, true);
-        treeEffectMap.insert(EffectMap::value_type(forest.texture, effect));
-    } else {
-        effect = iter->second.get();
-    }
-    // Now, create a quadtree for the forest.
-    {
+    MatrixTransform* mt = new MatrixTransform(transform);
+
+    SGTreeBinList::iterator i;
+
+    for (i = forestList.begin(); i != forestList.end(); ++i) {
+        TreeBin* forest = *i;
+      
+        Effect* effect = 0;
+        EffectMap::iterator iter = treeEffectMap.find(forest->texture);
+        if (iter == treeEffectMap.end()) {
+            SGPropertyNode_ptr effectProp = new SGPropertyNode;
+            makeChild(effectProp, "inherits-from")->setStringValue("Effects/tree");
+            SGPropertyNode* params = makeChild(effectProp, "parameters");
+            // emphasize n = 0
+            params->getChild("texture", 0, true)->getChild("image", 0, true)
+                ->setStringValue(forest->texture);
+            effect = makeEffect(effectProp, true);
+            treeEffectMap.insert(EffectMap::value_type(forest->texture, effect));
+        } else {
+            effect = iter->second.get();
+        }
+        
+        // Now, create a quadtree for the forest.
         ShaderGeometryQuadtree
             quadtree(GetTreeCoord(), AddTreesLeafObject(),
                      SG_TREE_QUAD_TREE_DEPTH,
-                     MakeTreesLeaf(forest.range, forest.texture_varieties,
-                                   forest.width, forest.height, effect));
+                     MakeTreesLeaf(forest->range, forest->texture_varieties,
+                                   forest->width, forest->height, effect));
         // Transform tree positions from the "geocentric" positions we
         // get from the scenery polys into the local Z-up coordinate
         // system.
         std::vector<TreeBin::Tree> rotatedTrees;
-        rotatedTrees.reserve(forest._trees.size());
-        std::transform(forest._trees.begin(), forest._trees.end(),
+        rotatedTrees.reserve(forest->_trees.size());
+        std::transform(forest->_trees.begin(), forest->_trees.end(),
                        std::back_inserter(rotatedTrees),
                        TreeTransformer(transInv));
         quadtree.buildQuadTree(rotatedTrees.begin(), rotatedTrees.end());
         group = quadtree.getRoot();
-    }
-    MatrixTransform* mt = new MatrixTransform(transform);
-    for (size_t i = 0; i < group->getNumChildren(); ++i)
-        mt->addChild(group->getChild(i));
+
+        for (size_t i = 0; i < group->getNumChildren(); ++i)
+            mt->addChild(group->getChild(i));
+    }
+    
     return mt;
 }
 

Modified: simgear/trunk/simgear/scene/tgdb/TreeBin.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/TreeBin.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/TreeBin.hxx (original)
+++ simgear/trunk/simgear/scene/tgdb/TreeBin.hxx Sun Jul 15 09:07:01 2012
@@ -49,7 +49,7 @@
     float height;
     float width;
     std::string texture;
-
+    
     void insert(const Tree& t)
     { _trees.push_back(t); }
     void insert(const SGVec3f& p, int t, float s)
@@ -62,6 +62,9 @@
     TreeList _trees;
 };
 
-osg::Group* createForest(TreeBin& forest, const osg::Matrix& transform);
+
+typedef std::list<TreeBin*> SGTreeBinList;
+
+osg::Group* createForest(SGTreeBinList& forestList, const osg::Matrix& transform);
 }
 #endif

Modified: simgear/trunk/simgear/scene/tgdb/apt_signs.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/apt_signs.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/apt_signs.cxx (original)
+++ simgear/trunk/simgear/scene/tgdb/apt_signs.cxx Sun Jul 15 09:07:01 2012
@@ -117,13 +117,13 @@
 
         if (*s == '{') {
             if (cmd)
-                SG_LOG(SG_TERRAIN, SG_ALERT, SIGN "unexpected { in sign contents");
+                SG_LOG(SG_TERRAIN, SG_ALERT, SIGN "Illegal taxiway sign syntax. Unexpected '{' in '" << content << "'.");
             cmd = true;
             continue;
 
         } else if (*s == '}') {
             if (!cmd)
-                SG_LOG(SG_TERRAIN, SG_ALERT, SIGN "unexpected } in sign contents");
+                SG_LOG(SG_TERRAIN, SG_ALERT, SIGN "Illegal taxiway sign syntax. Unexpected '{' in '" << content << "'.");
             cmd = false;
             continue;
 

Modified: simgear/trunk/simgear/scene/tgdb/obj.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/obj.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/obj.cxx (original)
+++ simgear/trunk/simgear/scene/tgdb/obj.cxx Sun Jul 15 09:07:01 2012
@@ -40,6 +40,8 @@
 #include <osg/StateSet>
 #include <osg/Switch>
 
+#include <boost/foreach.hpp>
+
 #include <simgear/debug/logstream.hxx>
 #include <simgear/io/sg_binobj.hxx>
 #include <simgear/math/sg_geodesy.hxx>
@@ -74,7 +76,7 @@
   SGMaterialTriangleMap materialTriangleMap;
   SGLightBin tileLights;
   SGLightBin randomTileLights;
-  TreeBin randomForest;
+  SGTreeBinList randomForest;
   SGDirectionalLightBin runwayLights;
   SGDirectionalLightBin taxiLights;
   SGDirectionalLightListBin vasiLights;
@@ -459,13 +461,33 @@
       float wood_coverage = mat->get_wood_coverage();
       if (wood_coverage <= 0)
         continue;
-
-      // Attributes that don't vary by tree
-      randomForest.texture = mat->get_tree_texture();
-      randomForest.range   = mat->get_tree_range();
-      randomForest.width   = mat->get_tree_width();
-      randomForest.height  = mat->get_tree_height();
-      randomForest.texture_varieties = mat->get_tree_varieties();
+              
+      // Attributes that don't vary by tree but do vary by material
+      bool found = false;
+      TreeBin* bin = NULL;
+      
+      BOOST_FOREACH(bin, randomForest)
+      {
+        if ((bin->texture           == mat->get_tree_texture()  ) &&
+            (bin->texture_varieties == mat->get_tree_varieties()) &&
+            (bin->range             == mat->get_tree_range()    ) &&
+            (bin->width             == mat->get_tree_width()    ) &&
+            (bin->height            == mat->get_tree_height()   )   ) {
+            found = true;
+            break;
+        }
+      }
+      
+      if (!found) {
+        bin = new TreeBin();
+        bin->texture = mat->get_tree_texture();
+          SG_LOG(SG_INPUT, SG_DEBUG, "Tree texture " << bin->texture);
+        bin->range   = mat->get_tree_range();
+        bin->width   = mat->get_tree_width();
+        bin->height  = mat->get_tree_height();
+        bin->texture_varieties = mat->get_tree_varieties();
+        randomForest.push_back(bin);
+      }
 
       std::vector<SGVec3f> randomPoints;
       i->second.addRandomTreePoints(wood_coverage,
@@ -473,9 +495,9 @@
                                     mat->get_wood_size(),
                                     randomPoints);
       
-      std::vector<SGVec3f>::iterator j;
-      for (j = randomPoints.begin(); j != randomPoints.end(); ++j) {
-        randomForest.insert(*j);
+      std::vector<SGVec3f>::iterator k;
+      for (k = randomPoints.begin(); k != randomPoints.end(); ++k) {
+        bin->insert(*k);
       }
     }
   }
@@ -557,11 +579,11 @@
                         GetModelLODCoord>  RandomObjectsQuadtree;
 
 osg::Node*
-SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects, bool use_random_vegetation)
+SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool use_random_objects, bool use_random_vegetation)
 {
   SGBinObject tile;
   if (!tile.read_bin(path))
-    return false;
+    return NULL;
 
   SGVec3d center = tile.get_gbs_center();
   SGGeod geodPos = SGGeod::fromCart(center);
@@ -582,14 +604,14 @@
 
   SGTileGeometryBin tileGeometryBin;
   if (!tileGeometryBin.insertBinObj(tile, matlib))
-    return false;
+    return NULL;
 
   SGVec3f up(0, 0, 1);
   GroundLightManager* lightManager = GroundLightManager::instance();
 
   osg::ref_ptr<osg::Group> lightGroup = new SGOffsetTransform(0.94);
   osg::ref_ptr<osg::Group> randomObjects;
-  osg::ref_ptr<osg::Group> randomForest;
+  osg::ref_ptr<osg::Group> forestNode;
   osg::Group* terrainGroup = new osg::Group;
 
   osg::Node* node = tileGeometryBin.getSurfaceGeometry(matlib);
@@ -639,47 +661,44 @@
     if (use_random_vegetation && matlib) {
       // Now add some random forest.
       tileGeometryBin.computeRandomForest(matlib);
-
-      if (tileGeometryBin.randomForest.getNumTrees() > 0) {
-        randomForest = createForest(tileGeometryBin.randomForest,
-                                    osg::Matrix::identity());
-        randomForest->setName("random trees");
+      
+      if (tileGeometryBin.randomForest.size() > 0) {
+        forestNode = createForest(tileGeometryBin.randomForest, osg::Matrix::identity());
+        forestNode->setName("Random trees");
       }
     } 
   }
 
-  if (calc_lights) {
-    // FIXME: ugly, has a side effect
-    if (matlib)
-      tileGeometryBin.computeRandomSurfaceLights(matlib);
-
-    if (tileGeometryBin.tileLights.getNumLights() > 0
-        || tileGeometryBin.randomTileLights.getNumLights() > 0) {
-      osg::Group* groundLights0 = new osg::Group;
-      groundLights0->setStateSet(lightManager->getGroundLightStateSet());
-      groundLights0->setNodeMask(GROUNDLIGHTS0_BIT);
-      osg::Geode* geode = new osg::Geode;
-      geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.tileLights));
-      geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 4, -0.3f));
-      groundLights0->addChild(geode);
-      lightGroup->addChild(groundLights0);
-    }
-    if (tileGeometryBin.randomTileLights.getNumLights() > 0) {
-      osg::Group* groundLights1 = new osg::Group;
-      groundLights1->setStateSet(lightManager->getGroundLightStateSet());
-      groundLights1->setNodeMask(GROUNDLIGHTS1_BIT);
-      osg::Group* groundLights2 = new osg::Group;
-      groundLights2->setStateSet(lightManager->getGroundLightStateSet());
-      groundLights2->setNodeMask(GROUNDLIGHTS2_BIT);
-      osg::Geode* geode = new osg::Geode;
-      geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 2, -0.15f));
-      groundLights1->addChild(geode);
-      lightGroup->addChild(groundLights1);
-      geode = new osg::Geode;
-      geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights));
-      groundLights2->addChild(geode);
-      lightGroup->addChild(groundLights2);
-    }
+  // FIXME: ugly, has a side effect
+  if (matlib)
+    tileGeometryBin.computeRandomSurfaceLights(matlib);
+
+  if (tileGeometryBin.tileLights.getNumLights() > 0
+      || tileGeometryBin.randomTileLights.getNumLights() > 0) {
+    osg::Group* groundLights0 = new osg::Group;
+    groundLights0->setStateSet(lightManager->getGroundLightStateSet());
+    groundLights0->setNodeMask(GROUNDLIGHTS0_BIT);
+    osg::Geode* geode = new osg::Geode;
+    geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.tileLights));
+    geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 4, -0.3f));
+    groundLights0->addChild(geode);
+    lightGroup->addChild(groundLights0);
+  }
+  if (tileGeometryBin.randomTileLights.getNumLights() > 0) {
+    osg::Group* groundLights1 = new osg::Group;
+    groundLights1->setStateSet(lightManager->getGroundLightStateSet());
+    groundLights1->setNodeMask(GROUNDLIGHTS1_BIT);
+    osg::Group* groundLights2 = new osg::Group;
+    groundLights2->setStateSet(lightManager->getGroundLightStateSet());
+    groundLights2->setNodeMask(GROUNDLIGHTS2_BIT);
+    osg::Geode* geode = new osg::Geode;
+    geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 2, -0.15f));
+    groundLights1->addChild(geode);
+    lightGroup->addChild(groundLights1);
+    geode = new osg::Geode;
+    geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights));
+    groundLights2->addChild(geode);
+    lightGroup->addChild(groundLights2);
   }
 
   if (!tileGeometryBin.vasiLights.empty()) {
@@ -770,14 +789,14 @@
     transform->addChild(lightLOD);
   }
   
-  if (randomObjects.valid() || randomForest.valid()) {
+  if (randomObjects.valid() || forestNode.valid()) {
   
     // Add a LoD node, so we don't try to display anything when the tile center
     // is more than 20km away.
     osg::LOD* objectLOD = new osg::LOD;
     
     if (randomObjects.valid()) objectLOD->addChild(randomObjects.get(), 0, 20000);
-    if (randomForest.valid())  objectLOD->addChild(randomForest.get(), 0, 20000);
+    if (forestNode.valid())  objectLOD->addChild(forestNode.get(), 0, 20000);
     
     unsigned nodeMask = SG_NODEMASK_CASTSHADOW_BIT | SG_NODEMASK_RECIEVESHADOW_BIT | SG_NODEMASK_TERRAIN_BIT;
     objectLOD->setNodeMask(nodeMask);

Modified: simgear/trunk/simgear/scene/tgdb/obj.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/obj.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/obj.hxx (original)
+++ simgear/trunk/simgear/scene/tgdb/obj.hxx Sun Jul 15 09:07:01 2012
@@ -56,6 +56,6 @@
 }
 
 osg::Node*
-SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects, bool use_random_vegetation);
+SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool use_random_objects, bool use_random_vegetation);
 
 #endif // _SG_OBJ_HXX

Modified: simgear/trunk/simgear/scene/tgdb/pt_lights.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tgdb/pt_lights.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tgdb/pt_lights.cxx (original)
+++ simgear/trunk/simgear/scene/tgdb/pt_lights.cxx Sun Jul 15 09:07:01 2012
@@ -407,8 +407,21 @@
     drawable->addLight(lights.getLight(3).position,
                        lights.getLight(3).normal, up, 2.5);
     return drawable;
-  }
-  else if (count == 12) {
+
+  } else if (count == 6) {
+    SGVasiDrawable* drawable = new SGVasiDrawable(red, white);
+
+    // probably vasi, first 3 are downwind bar (2.5 deg)
+    for (unsigned i = 0; i < 3; ++i)
+      drawable->addLight(lights.getLight(i).position,
+                         lights.getLight(i).normal, up, 2.5);
+    // last 3 are upwind bar (3.0 deg)
+    for (unsigned i = 3; i < 6; ++i)
+      drawable->addLight(lights.getLight(i).position,
+                         lights.getLight(i).normal, up, 3.0);
+    return drawable;
+
+  } else if (count == 12) {
     SGVasiDrawable* drawable = new SGVasiDrawable(red, white);
     
     // probably vasi, first 6 are downwind bar (2.5 deg)
@@ -419,8 +432,8 @@
     for (unsigned i = 6; i < 12; ++i)
       drawable->addLight(lights.getLight(i).position,
                          lights.getLight(i).normal, up, 3.0);
-    
     return drawable;
+
   } else {
     // fail safe
     SG_LOG(SG_TERRAIN, SG_ALERT,

Modified: simgear/trunk/simgear/scene/tsync/terrasync.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tsync/terrasync.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tsync/terrasync.cxx (original)
+++ simgear/trunk/simgear/scene/tsync/terrasync.cxx Sun Jul 15 09:07:01 2012
@@ -45,6 +45,7 @@
 
 #include <stdlib.h>             // atoi() atof() abs() system()
 #include <signal.h>             // signal()
+#include <string.h>
 
 #include <iostream>
 #include <fstream>
@@ -58,9 +59,7 @@
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/misc/strutils.hxx>
 #include <simgear/threads/SGQueue.hxx>
-#include <simgear/scene/tgdb/TileCache.hxx>
 #include <simgear/misc/sg_dir.hxx>
-#include <OpenThreads/Thread>
 
 #ifdef HAVE_SVN_CLIENT_H
 #  ifdef HAVE_LIBSVN_CLIENT_1
@@ -86,6 +85,7 @@
 #endif
 
 using namespace simgear;
+using namespace std;
 
 const char* rsync_cmd = 
         "rsync --verbose --archive --delete --perms --owner --group";
@@ -139,7 +139,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 // SGTerraSync::SvnThread /////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-class SGTerraSync::SvnThread : public OpenThreads::Thread
+class SGTerraSync::SvnThread : public SGThread
 {
 public:
    SvnThread();
@@ -160,6 +160,7 @@
    void   setLocalDir(string dir)           { _local_dir    = stripPath(dir);}
    string getLocalDir()                     { return _local_dir;}
    void   setUseSvn(bool use_svn)           { _use_svn = use_svn;}
+   void   setAllowedErrorCount(int errors)  {_allowed_errors = errors;}
 
 #ifdef HAVE_SVN_CLIENT_H
    void setUseBuiltin(bool built_in) { _use_built_in = built_in;}
@@ -173,6 +174,7 @@
    volatile int  _updated_tile_count;
    volatile int  _success_count;
    volatile int  _consecutive_errors;
+   volatile int  _allowed_errors;
 
 private:
    virtual void run();
@@ -220,6 +222,7 @@
     _updated_tile_count(0),
     _success_count(0),
     _consecutive_errors(0),
+    _allowed_errors(6),
 #ifdef HAVE_SVN_CLIENT_H
     _use_built_in(true),
 #endif
@@ -342,7 +345,7 @@
            << status
            << "Directory: '" << _local_dir << "'.");
 
-    OpenThreads::Thread::start();
+    SGThread::start();
     return true;
 }
 
@@ -485,7 +488,18 @@
     command = buf.str();
 #endif
     SG_LOG(SG_TERRAIN,SG_DEBUG, "sync command '" << command << "'");
+
+#ifdef SG_WINDOWS
+    // tbd: does Windows support "popen"?
     int rc = system( command.c_str() );
+#else
+    FILE* pipe = popen( command.c_str(), "r");
+    int rc=-1;
+    // wait for external process to finish
+    if (pipe)
+        rc = pclose(pipe);
+#endif
+
     if (rc)
     {
         SG_LOG(SG_TERRAIN,SG_ALERT,
@@ -543,7 +557,8 @@
             _busy = false;
         }
 
-        if (_consecutive_errors >= 5)
+        if ((_allowed_errors >= 0)&&
+            (_consecutive_errors >= _allowed_errors))
         {
             _stalled = true;
             _stop = true;
@@ -657,7 +672,8 @@
     last_lat(NOWHERE),
     last_lon(NOWHERE),
     _terraRoot(root->getNode("/sim/terrasync",true)),
-    _tile_cache(NULL)
+    _refreshCb(NULL),
+    _userCbData(NULL)
 {
     _svnThread = new SvnThread();
 }
@@ -671,7 +687,7 @@
 
 void SGTerraSync::init()
 {
-    _refresh_display = _terraRoot->getNode("refresh-display",true);
+    _refreshDisplay = _terraRoot->getNode("refresh-display",true);
     _terraRoot->getNode("built-in-svn-available",true)->setBoolValue(svn_built_in_available);
     reinit();
 }
@@ -690,6 +706,7 @@
         _svnThread->setSvnServer(_terraRoot->getStringValue("svn-server",""));
         _svnThread->setRsyncServer(_terraRoot->getStringValue("rsync-server",""));
         _svnThread->setLocalDir(_terraRoot->getStringValue("scenery-dir",""));
+        _svnThread->setAllowedErrorCount(_terraRoot->getIntValue("max-errors",5));
 
     #ifdef HAVE_SVN_CLIENT_H
         _svnThread->setUseBuiltin(_terraRoot->getBoolValue("use-built-in-svn",true));
@@ -700,12 +717,21 @@
         _svnThread->setExtSvnUtility(_terraRoot->getStringValue("ext-svn-utility","svn"));
 
         if (_svnThread->start())
+        {
             syncAirportsModels();
-    }
-
-    _stalled_node->setBoolValue(_svnThread->_stalled);
-    last_lat = NOWHERE;
-    last_lon = NOWHERE;
+            if (last_lat != NOWHERE && last_lon != NOWHERE)
+            {
+                // reschedule most recent position
+                int lat = last_lat;
+                int lon = last_lon;
+                last_lat = NOWHERE;
+                last_lon = NOWHERE;
+                schedulePosition(lat, lon);
+            }
+        }
+    }
+
+    _stalledNode->setBoolValue(_svnThread->_stalled);
 }
 
 void SGTerraSync::bind()
@@ -723,9 +749,9 @@
     _terraRoot->getNode("use-built-in-svn", true)->setAttribute(SGPropertyNode::USERARCHIVE,false);
     _terraRoot->getNode("use-svn", true)->setAttribute(SGPropertyNode::USERARCHIVE,false);
     // stalled is used as a signal handler (to connect listeners triggering GUI pop-ups)
-    _stalled_node = _terraRoot->getNode("stalled", true);
-    _stalled_node->setBoolValue(_svnThread->_stalled);
-    _stalled_node->setAttribute(SGPropertyNode::PRESERVE,true);
+    _stalledNode = _terraRoot->getNode("stalled", true);
+    _stalledNode->setBoolValue(_svnThread->_stalled);
+    _stalledNode->setAttribute(SGPropertyNode::PRESERVE,true);
 }
 
 void SGTerraSync::unbind()
@@ -752,10 +778,10 @@
                 SG_LOG(SG_TERRAIN,SG_ALERT,
                         "Automatic scenery download/synchronization has stopped.");
             }
-            _stalled_node->setBoolValue(_svnThread->_stalled);
-        }
-
-        if (!_refresh_display->getBoolValue())
+            _stalledNode->setBoolValue(_svnThread->_stalled);
+        }
+
+        if (!_refreshDisplay->getBoolValue())
             return;
 
         while (_svnThread->hasNewTiles())
@@ -772,7 +798,7 @@
 void SGTerraSync::refreshScenery(SGPath path,const string& relativeDir)
 {
     // find tiles to be refreshed
-    if (_tile_cache)
+    if (_refreshCb)
     {
         path.append(relativeDir);
         if (path.exists())
@@ -786,7 +812,7 @@
             {
                 // reload scenery tile
                 long index = atoi(tileList[i].file().c_str());
-                _tile_cache->refresh_tile(index);
+                _refreshCb(_userCbData, index);
             }
         }
     }
@@ -794,17 +820,19 @@
 
 bool SGTerraSync::isIdle() {return _svnThread->isIdle();}
 
-void SGTerraSync::setTileCache(TileCache* tile_cache)
-{
-    _tile_cache = tile_cache;
+void SGTerraSync::setTileRefreshCb(SGTerraSyncCallback refreshCb, void* userCbData)
+{
+    _refreshCb = refreshCb;
+    _userCbData = userCbData;
 }
 
 void SGTerraSync::syncAirportsModels()
 {
-    static const char bounds[] = "KZAJ";
-    for( unsigned i = 0; i < sizeof(bounds)/sizeof(bounds[0])/2; i+= 2 ) 
-    {
-        for ( char synced_other = bounds[i]; synced_other <= bounds[i+1]; synced_other++ )
+    static const char* bounds = "MZAJKL"; // airport sync order: K-L, A-J, M-Z
+    // note "request" method uses LIFO order, i.e. processes most recent request first
+    for( unsigned i = 0; i < strlen(bounds)/2; i++ )
+    {
+        for ( char synced_other = bounds[2*i]; synced_other <= bounds[2*i+1]; synced_other++ )
         {
             ostringstream dir;
             dir << "Airports/" << synced_other;
@@ -895,46 +923,49 @@
 
 bool SGTerraSync::schedulePosition(int lat, int lon)
 {
+    bool Ok = false;
+
     // Ignore messages where the location does not change
     if ( lat != last_lat || lon != last_lon )
     {
-        SG_LOG(SG_TERRAIN,SG_DEBUG, "Requesting scenery update for position " << 
-                                    lat << "," << lon);
-        int lat_dir, lon_dir, dist;
-        if ( last_lat == NOWHERE || last_lon == NOWHERE )
-        {
-            lat_dir = lon_dir = 0;
-        } else
-        {
-            dist = lat - last_lat;
-            if ( dist != 0 )
+        if (_svnThread->_running)
+        {
+            SG_LOG(SG_TERRAIN,SG_DEBUG, "Requesting scenery update for position " <<
+                                        lat << "," << lon);
+            int lat_dir=0;
+            int lon_dir=0;
+            if ( last_lat != NOWHERE && last_lon != NOWHERE )
             {
-                lat_dir = dist / abs(dist);
+                int dist = lat - last_lat;
+                if ( dist != 0 )
+                {
+                    lat_dir = dist / abs(dist);
+                }
+                else
+                {
+                    lat_dir = 0;
+                }
+                dist = lon - last_lon;
+                if ( dist != 0 )
+                {
+                    lon_dir = dist / abs(dist);
+                } else
+                {
+                    lon_dir = 0;
+                }
             }
-            else
-            {
-                lat_dir = 0;
-            }
-            dist = lon - last_lon;
-            if ( dist != 0 )
-            {
-                lon_dir = dist / abs(dist);
-            } else
-            {
-                lon_dir = 0;
-            }
-        }
-
-        SG_LOG(SG_TERRAIN,SG_DEBUG, "Scenery update for " << 
-               "lat = " << lat << ", lon = " << lon <<
-               ", lat_dir = " << lat_dir << ",  " <<
-               "lon_dir = " << lon_dir);
-
-        syncAreas( lat, lon, lat_dir, lon_dir );
-
+
+            SG_LOG(SG_TERRAIN,SG_DEBUG, "Scenery update for " <<
+                   "lat = " << lat << ", lon = " << lon <<
+                   ", lat_dir = " << lat_dir << ",  " <<
+                   "lon_dir = " << lon_dir);
+
+            syncAreas( lat, lon, lat_dir, lon_dir );
+            Ok = true;
+        }
         last_lat = lat;
         last_lon = lon;
-        return true;
-    }
-    return false;
-}
+    }
+
+    return Ok;
+}

Modified: simgear/trunk/simgear/scene/tsync/terrasync.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/tsync/terrasync.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/tsync/terrasync.hxx (original)
+++ simgear/trunk/simgear/scene/tsync/terrasync.hxx Sun Jul 15 09:07:01 2012
@@ -24,7 +24,6 @@
 #include <simgear/props/props.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
 #include <simgear/props/tiedpropertylist.hxx>
-#include <OpenThreads/Thread>
 
 class SGPath;
 
@@ -32,7 +31,7 @@
 {
 const int NOWHERE = -9999;
 
-class TileCache;
+typedef void (*SGTerraSyncCallback)(void* userData, long tileIndex);
 
 class SGTerraSync : public SGSubsystem
 {
@@ -48,13 +47,13 @@
 
     bool isIdle();
     bool schedulePosition(int lat, int lon);
-    void setTileCache(TileCache* tile_cache);
+    void setTileRefreshCb(SGTerraSyncCallback refreshCb, void* userData = NULL);
 
 protected:
     void syncAirportsModels();
     void syncArea(int lat, int lon);
     void syncAreas(int lat, int lon, int lat_dir, int lon_dir);
-    void refreshScenery(SGPath path,const string& relativeDir);
+    void refreshScenery(SGPath path,const std::string& relativeDir);
 
     class SvnThread;
 
@@ -63,9 +62,10 @@
     int last_lat;
     int last_lon;
     SGPropertyNode_ptr _terraRoot;
-    SGPropertyNode_ptr _refresh_display;
-    SGPropertyNode_ptr _stalled_node;
-    TileCache* _tile_cache;
+    SGPropertyNode_ptr _refreshDisplay;
+    SGPropertyNode_ptr _stalledNode;
+    SGTerraSyncCallback _refreshCb;
+    void* _userCbData;
     simgear::TiedPropertyList _tiedProperties;
 };
 

Modified: simgear/trunk/simgear/scene/util/SGSceneUserData.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/util/SGSceneUserData.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/util/SGSceneUserData.hxx (original)
+++ simgear/trunk/simgear/scene/util/SGSceneUserData.hxx Sun Jul 15 09:07:01 2012
@@ -34,7 +34,8 @@
   SGSceneUserData() {}
   SGSceneUserData(const SGSceneUserData& rhs,
                   const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
-    : _bvhNode(rhs._bvhNode), _velocity(rhs._velocity),
+    : osg::Object(rhs,copyOp),
+      _bvhNode(rhs._bvhNode), _velocity(rhs._velocity),
       _pickCallbacks(rhs._pickCallbacks)
   {
   }

Modified: simgear/trunk/simgear/scene/util/StateAttributeFactory.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/util/StateAttributeFactory.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/util/StateAttributeFactory.cxx (original)
+++ simgear/trunk/simgear/scene/util/StateAttributeFactory.cxx Sun Jul 15 09:07:01 2012
@@ -86,4 +86,10 @@
     _depthWritesDisabled->setDataVariance(Object::STATIC);
 }
 
+// anchor the destructor into this file, to avoid ref_ptr warnings
+StateAttributeFactory::~StateAttributeFactory()
+{
+  
 }
+  
+}

Modified: simgear/trunk/simgear/scene/util/StateAttributeFactory.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/scene/util/StateAttributeFactory.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/scene/util/StateAttributeFactory.hxx (original)
+++ simgear/trunk/simgear/scene/util/StateAttributeFactory.hxx Sun Jul 15 09:07:01 2012
@@ -45,6 +45,8 @@
 class StateAttributeFactory :
         public ReferencedSingleton<StateAttributeFactory> {
 public:
+    ~StateAttributeFactory();
+          
     // Alpha test > .01
     osg::AlphaFunc* getStandardAlphaFunc() { return _standardAlphaFunc.get(); }
     // alpha source, 1 - alpha destination

Modified: simgear/trunk/simgear/screen/screen-dump.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/screen/screen-dump.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/screen/screen-dump.cxx (original)
+++ simgear/trunk/simgear/screen/screen-dump.cxx Sun Jul 15 09:07:01 2012
@@ -65,9 +65,15 @@
 	    for (k = 0; k < RGB3; k++)
 		ibuffer[q++] = (unsigned char)
 		    *(buffer + (pixelSize*((win_height-1-i)*win_width+j)+k));
-    fwrite(ibuffer, sizeof(unsigned char), RGB3*win_width*win_height, fp);
+    int written = fwrite(ibuffer, sizeof(unsigned char), RGB3*win_width*win_height, fp);
     fclose(fp);
     free(ibuffer);
+
+    if ( written != RGB3*win_width*win_height )
+    {
+        printf("Warning: failed to write %s. File truncated.\n", filename);
+        return false;
+    }
 
     printf("wrote file '%s' (%d x %d pixels, %d bytes)\n",
 	   filename, win_width, win_height, RGB3*win_width*win_height);

Modified: simgear/trunk/simgear/screen/tr.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/screen/tr.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/screen/tr.cxx (original)
+++ simgear/trunk/simgear/screen/tr.cxx Sun Jul 15 09:07:01 2012
@@ -144,7 +144,7 @@
 #include <windows.h>
 #endif
 
-#include <simgear/math/project.hxx>
+#include <simgear/scene/util/project.hxx>
 
 #include "tr.h"
 
@@ -408,7 +408,7 @@
 {
    GLint matrixMode;
    GLint tileWidth, tileHeight, border;
-   GLdouble left, right, bottom, top;
+//   GLdouble left, right, bottom, top;
 
    if (!tr)
       return;
@@ -459,7 +459,9 @@
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
 
+   // OSGFIXME
    /* compute projection parameters */
+   /*
    left = tr->Left + (tr->Right - tr->Left)
         * (tr->CurrentColumn * tr->TileWidthNB - border) / tr->ImageWidth;
    right = left + (tr->Right - tr->Left) * tileWidth / tr->ImageWidth;
@@ -467,8 +469,8 @@
           * (tr->CurrentRow * tr->TileHeightNB - border) / tr->ImageHeight;
    top = bottom + (tr->Top - tr->Bottom) * tileHeight / tr->ImageHeight;
 
-   // OSGFIXME
-//    ssgSetFrustum ( left, right, bottom, top, tr->Near, tr->Far );
+    ssgSetFrustum ( left, right, bottom, top, tr->Near, tr->Far );
+   */
 
    /* restore user's matrix mode */
    glMatrixMode( (GLenum)matrixMode );

Modified: simgear/trunk/simgear/sg_inlines.h
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sg_inlines.h?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sg_inlines.h (original)
+++ simgear/trunk/simgear/sg_inlines.h Sun Jul 15 09:07:01 2012
@@ -98,6 +98,6 @@
     T step = max - min;
     while( val >= max )  val -= step;
     while( val < min ) val += step;
-};
+}
 
 #endif // _SG_INLINES_H

Modified: simgear/trunk/simgear/sound/openal_test1.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sound/openal_test1.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sound/openal_test1.cxx (original)
+++ simgear/trunk/simgear/sound/openal_test1.cxx Sun Jul 15 09:07:01 2012
@@ -103,10 +103,6 @@
     ALfloat source_vel[3];
 
     // configuration values
-//    ALenum format;
-//    ALsizei size;
-//    ALvoid* data;
-//    ALsizei freq;
     ALboolean loop = false;
 
     source_pos[0] = 0.0; source_pos[1] = 0.0; source_pos[2] = 0.0;
@@ -131,6 +127,11 @@
   }
 
 #else
+  ALenum format;
+  ALsizei size;
+  ALvoid* data;
+  ALsizei freq;
+  
 # if defined (__APPLE__)
     alutLoadWAVFile( (ALbyte *)AUDIOFILE, &format, &data, &size, &freq );
 # else

Modified: simgear/trunk/simgear/sound/sample_group.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sound/sample_group.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sound/sample_group.cxx (original)
+++ simgear/trunk/simgear/sound/sample_group.cxx Sun Jul 15 09:07:01 2012
@@ -94,18 +94,27 @@
         ALint result = AL_STOPPED;
 
         if ( sample->is_valid_source() ) {
+            int source = sample->get_source();
+
+            alGetSourcei( source, AL_SOURCE_STATE, &result );
             if ( sample->is_looping() ) {
-                sample->no_valid_source();
-                _smgr->release_source( sample->get_source() );
-            }
-            else
-                alGetSourcei( sample->get_source(), AL_SOURCE_STATE, &result );
+                if ( result != AL_STOPPED ) {
+                    alSourceStop( source );
+                    alGetSourcei( source, AL_SOURCE_STATE, &result );
+                }
+                if ( result == AL_STOPPED ) {
+                    sample->no_valid_source();
+                    _smgr->release_source( sample->get_source() );
+                }
+            }
         }
 
         if ( result == AL_STOPPED ) {
             sample->stop();
             if ( !sample->is_queue() ) {
                 ALuint buffer = sample->get_buffer();
+                // disconnect buffer from its source - otherwise it cannot be deleted
+                alSourceUnqueueBuffers(sample->get_source(), 1, &buffer);
                 alDeleteBuffers( 1, &buffer );
                 testForALError("buffer remove");
             }
@@ -148,11 +157,16 @@
                 }
                 else
                 {
-                    if (_smgr->request_buffer(sample) == SGSoundMgr::NO_BUFFER)
+                    ALuint buffer = _smgr->request_buffer(sample);
+                    if (buffer == SGSoundMgr::FAILED_BUFFER ||
+                        buffer == SGSoundMgr::NO_BUFFER)
+                    {
+                        _smgr->release_source(source);
                         continue;
+                    }
 
                     // start playing the sample
-                    ALuint buffer = sample->get_buffer();
+                    buffer = sample->get_buffer();
                     if ( alIsBuffer(buffer) == AL_TRUE )
                     {
                         alSourcei( source, AL_BUFFER, buffer );
@@ -167,7 +181,7 @@
                         alSourcePlay( source );
                         testForALError("sample play");
                     } else
-                        SG_LOG( SG_GENERAL, SG_ALERT, "No such buffer!\n");
+                        SG_LOG( SG_SOUND, SG_ALERT, "No such buffer!\n");
                 }
             }
 
@@ -392,6 +406,19 @@
         sample->set_rotation( ec2body );
         sample->set_position( position );
         sample->set_velocity( velocity );
+
+        // Test if a sample is farther away than max distance, if so
+        // stop the sound playback and free it's source.
+        if (!_tied_to_listener) {
+            float max2 = sample->get_max_dist() * sample->get_max_dist();
+            float dist2 = position[0]*position[0]
+                          + position[1]*position[1] + position[2]*position[2];
+            if ((dist2 > max2) && !sample->test_out_of_range()) {
+                sample->set_out_of_range(true);
+            } else if ((dist2 < max2) && sample->test_out_of_range()) {
+                sample->set_out_of_range(false);
+            }
+        }
     }
 }
 
@@ -449,7 +476,7 @@
 bool SGSampleGroup::testForError(void *p, string s)
 {
    if (p == NULL) {
-      SG_LOG( SG_GENERAL, SG_ALERT, "Error (sample group): " << s);
+      SG_LOG( SG_SOUND, SG_ALERT, "Error (sample group): " << s);
       return true;
    }
    return false;
@@ -459,7 +486,7 @@
 {
     ALenum error = alGetError();
     if (error != AL_NO_ERROR)  {
-       SG_LOG( SG_GENERAL, SG_ALERT, "AL Error (" << _refname << "): "
+       SG_LOG( SG_SOUND, SG_ALERT, "AL Error (" << _refname << "): "
                                       << alGetString(error) << " at " << s);
        return true;
     }

Modified: simgear/trunk/simgear/sound/sample_group.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sound/sample_group.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sound/sample_group.hxx (original)
+++ simgear/trunk/simgear/sound/sample_group.hxx Sun Jul 15 09:07:01 2012
@@ -180,7 +180,7 @@
     /**
      * Request to stop playing the refered audio sample.
      * @param refname Reference name of the audio sample to stop
-     * @return true if the audio sample exsists and is scheduled to stop
+     * @return true if the audio sample exists and is scheduled to stop
      */
     bool stop( const string& refname );
 

Modified: simgear/trunk/simgear/sound/sample_openal.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sound/sample_openal.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sound/sample_openal.cxx (original)
+++ simgear/trunk/simgear/sound/sample_openal.cxx Sun Jul 15 09:07:01 2012
@@ -74,6 +74,7 @@
     _playing(false),
     _changed(true),
     _static_changed(true),
+    _out_of_range(false),
     _is_file(false)
 {
 }
@@ -109,6 +110,7 @@
     _playing(false),
     _changed(true),
     _static_changed(true),
+    _out_of_range(false),
     _is_file(true)
 {
     SGPath p = simgear::ResourceManager::instance()->findPath(file, currentDir);
@@ -146,9 +148,10 @@
     _playing(false),
     _changed(true),
     _static_changed(true),
+    _out_of_range(false),
     _is_file(false)
 {
-    SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" );
+    SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
     _data = (unsigned char*)*data; *data = NULL;
 }
 
@@ -182,9 +185,10 @@
     _playing(false),
     _changed(true),
     _static_changed(true),
+    _out_of_range(false),
     _is_file(false)
 {
-    SG_LOG( SG_GENERAL, SG_DEBUG, "In memory sounds sample" );
+    SG_LOG( SG_SOUND, SG_DEBUG, "In memory sounds sample" );
     _data = (unsigned char*)*data; *data = NULL;
 }
 

Modified: simgear/trunk/simgear/sound/sample_openal.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sound/sample_openal.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sound/sample_openal.hxx (original)
+++ simgear/trunk/simgear/sound/sample_openal.hxx Sun Jul 15 09:07:01 2012
@@ -82,10 +82,10 @@
     /**
      * Destructor
      */
-    ~SGSoundSample ();
-
-    /**
-     * Detect wheter this audio sample holds the information of a sound file.
+    virtual ~SGSoundSample ();
+
+    /**
+     * Detect whether this audio sample holds the information of a sound file.
      * @return Return true if this audio sample is to be constructed from a file.
      */
     inline bool is_file() const { return _is_file; }
@@ -103,7 +103,7 @@
     }
 
     /**
-     * Test if static dataa of audio sample configuration has changed.
+     * Test if static data of audio sample configuration has changed.
      * Calling this function will reset the flag so calling it a second
      * time in a row will return false.
      * @return Return true is the static data has changed in the mean time.
@@ -118,7 +118,7 @@
      * @param _loop Define whether this sound should be played in a loop.
      */
     void play( bool loop = false ) {
-        _playing = true; _loop = loop; _changed = true;
+        _playing = true; _loop = loop; _changed = true; _static_changed = true;
     }
 
     /**
@@ -151,6 +151,22 @@
      * @return true if this audio sample is playing, false otherwise.
      */
     inline bool is_playing() { return _playing; }
+
+
+    /**
+     * Set this sample to out-of-range (or not) and
+     * Schedule this audio sample to stop (or start) playing.
+     */
+    inline void set_out_of_range(bool oor = true) {
+        _out_of_range = oor; _playing = (!oor && _loop); _changed = true;
+    }
+
+    /**
+     * Test if this sample to out-of-range or not.
+     */
+    inline bool test_out_of_range() {
+        return _out_of_range;
+    }
 
     /**
      * Set the data associated with this audio sample
@@ -495,6 +511,7 @@
     bool _playing;
     bool _changed;
     bool _static_changed;
+    bool _out_of_range;
     bool _is_file;
 
     string random_string();

Modified: simgear/trunk/simgear/sound/soundmgr_openal.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sound/soundmgr_openal.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sound/soundmgr_openal.cxx (original)
+++ simgear/trunk/simgear/sound/soundmgr_openal.cxx Sun Jul 15 09:07:01 2012
@@ -47,6 +47,7 @@
 #include <simgear/math/SGMath.hxx>
 
 using std::string;
+using std::vector;
 
 extern bool isNaN(float *v);
 
@@ -110,7 +111,7 @@
 // initialize the sound manager
 void SGSoundMgr::init(const char *devname) {
 
-    SG_LOG( SG_GENERAL, SG_INFO, "Initializing OpenAL sound manager" );
+    SG_LOG( SG_SOUND, SG_INFO, "Initializing OpenAL sound manager" );
 
     ALCdevice *device = alcOpenDevice(devname);
     if ( testForError(device, "Audio device not available, trying default") ) {
@@ -136,7 +137,7 @@
     }
 
     if (_context != NULL)
-        SG_LOG(SG_GENERAL, SG_ALERT, "context is already assigned");
+        SG_LOG(SG_SOUND, SG_ALERT, "context is already assigned");
     _context = context;
     _working = true;
 
@@ -183,7 +184,7 @@
     }
 
     if (_free_sources.size() == 0) {
-        SG_LOG(SG_GENERAL, SG_ALERT, "Unable to grab any OpenAL sources!");
+        SG_LOG(SG_SOUND, SG_ALERT, "Unable to grab any OpenAL sources!");
     }
 }
 
@@ -214,6 +215,7 @@
     for (unsigned int i=0; i<_free_sources.size(); i++) {
         ALuint source = _free_sources[i];
         alDeleteSources( 1 , &source );
+        testForALError("SGSoundMgr::stop: delete sources");
     }
     _free_sources.clear();
 
@@ -224,6 +226,7 @@
         refUint ref = buffers_current->second;
         ALuint buffer = ref.id;
         alDeleteBuffers(1, &buffer);
+        testForALError("SGSoundMgr::stop: delete buffers");
     }
     _buffers.clear();
 
@@ -282,6 +285,7 @@
     for (unsigned int i=0; i<_free_sources.size(); i++) {
         ALuint source = _free_sources[i];
         alDeleteSources( 1 , &source );
+        testForALError("SGSoundMgr::unbind: delete sources");
     }
 
     _free_sources.clear();
@@ -411,7 +415,7 @@
 // and hence orientation) of the sources.
 //
 // The Sound Manager is (and should be) the only one knowing about source
-// management. Sources further away should be suspendped to free resources for
+// management. Sources further away should be suspended to free resources for
 // newly added sounds close by.
 unsigned int SGSoundMgr::request_source()
 {
@@ -423,7 +427,7 @@
        _sources_in_use.push_back(source);
     }
     else
-       SG_LOG( SG_GENERAL, SG_INFO, "No more free sources available\n");
+       SG_LOG( SG_SOUND, SG_BULK, "Sound manager: No more free sources available!\n");
 
     return source;
 }
@@ -438,7 +442,7 @@
         ALint result;
 
         alGetSourcei( source, AL_SOURCE_STATE, &result );
-        if ( result == AL_PLAYING ) {
+        if ( result == AL_PLAYING || result == AL_PAUSED ) {
             alSourceStop( source );
         }
 
@@ -476,9 +480,10 @@
               bool res = load(sample_name, &sample_data, &format, &size, &freq);
               if (res == false) return NO_BUFFER;
             } catch (sg_exception& e) {
-              SG_LOG(SG_GENERAL, SG_ALERT,
-                     "failed to load sound buffer:" << e.getFormattedMessage());
-              return NO_BUFFER;
+              SG_LOG(SG_SOUND, SG_ALERT,
+                    "failed to load sound buffer: " << e.getFormattedMessage());
+              sample->set_buffer( SGSoundMgr::FAILED_BUFFER );
+              return FAILED_BUFFER;
             }
             
             sample->set_frequency( freq );
@@ -604,7 +609,7 @@
             // occurs: e.g. -43 on Mac when file is not found.
             // In this case, alGetString() sets 'Invalid Enum' error, so
             // showing with the original error number is helpful.
-            stringstream ss;
+            std::stringstream ss;
             ss << alGetString(alGetError()) << "(" << error << ")";
             msg.append(ss.str());
         }
@@ -612,6 +617,11 @@
         return false;
     }
 #endif
+
+    if (format == AL_FORMAT_STEREO8 || format == AL_FORMAT_STEREO16) {
+        free(data);
+        throw sg_io_exception("Warning: STEREO files are not supported for 3D audio effects: " + samplepath);
+    }
 
     *dbuf = (void *)data;
     *fmt = (int)format;
@@ -651,7 +661,7 @@
 bool SGSoundMgr::testForError(void *p, string s)
 {
    if (p == NULL) {
-      SG_LOG( SG_GENERAL, SG_ALERT, "Error: " << s);
+      SG_LOG( SG_SOUND, SG_ALERT, "Error: " << s);
       return true;
    }
    return false;
@@ -662,7 +672,7 @@
 {
     ALenum error = alGetError();
     if (error != AL_NO_ERROR)  {
-       SG_LOG( SG_GENERAL, SG_ALERT, "AL Error (sound manager): "
+       SG_LOG( SG_SOUND, SG_ALERT, "AL Error (sound manager): "
                                       << alGetString(error) << " at " << s);
        return true;
     }
@@ -674,7 +684,7 @@
     ALCenum error;
     error = alcGetError(_device);
     if (error != ALC_NO_ERROR) {
-        SG_LOG( SG_GENERAL, SG_ALERT, "ALC Error (sound manager): "
+        SG_LOG( SG_SOUND, SG_ALERT, "ALC Error (sound manager): "
                                        << alcGetString(_device, error) << " at "
                                        << s);
         return true;
@@ -688,7 +698,7 @@
     ALenum error;
     error =  alutGetError ();
     if (error != ALUT_ERROR_NO_ERROR) {
-        SG_LOG( SG_GENERAL, SG_ALERT, "ALUT Error (sound manager): "
+        SG_LOG( SG_SOUND, SG_ALERT, "ALUT Error (sound manager): "
                                        << alutGetErrorString(error) << " at "
                                        << s);
         return true;

Modified: simgear/trunk/simgear/sound/soundmgr_openal.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sound/soundmgr_openal.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sound/soundmgr_openal.hxx (original)
+++ simgear/trunk/simgear/sound/soundmgr_openal.hxx Sun Jul 15 09:07:01 2012
@@ -200,7 +200,8 @@
 
     enum {
         NO_SOURCE = (unsigned int)-1,
-        NO_BUFFER = (unsigned int)-1
+        NO_BUFFER = (unsigned int)-1,
+        FAILED_BUFFER = (unsigned int)-2
     };
 
     /**

Modified: simgear/trunk/simgear/sound/xmlsound.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sound/xmlsound.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sound/xmlsound.cxx (original)
+++ simgear/trunk/simgear/sound/xmlsound.cxx Sun Jul 15 09:07:01 2012
@@ -30,6 +30,7 @@
 #include <string.h>
 
 #include <simgear/debug/logstream.hxx>
+#include <simgear/props/props.hxx>
 #include <simgear/props/condition.hxx>
 #include <simgear/math/SGMath.hxx>
 #include <simgear/structure/exception.hxx>
@@ -93,7 +94,7 @@
    //
 
    _name = node->getStringValue("name", "");
-   SG_LOG(SG_GENERAL, SG_DEBUG, "Loading sound information for: " << _name );
+   SG_LOG(SG_SOUND, SG_DEBUG, "Loading sound information for: " << _name );
 
    string mode_str = node->getStringValue("mode", "");
    if ( mode_str == "looped" ) {
@@ -120,7 +121,7 @@
       _condition = sgReadCondition(root, condition);
 
    if (!_property && !_condition)
-      SG_LOG(SG_GENERAL, SG_WARN,
+      SG_LOG(SG_SOUND, SG_WARN,
              "  Neither a condition nor a property specified");
 
    _delay = node->getDoubleValue("delay-sec", 0.0);
@@ -160,19 +161,19 @@
             }
 
          if (!volume.fn)
-            SG_LOG(SG_GENERAL,SG_INFO,
+            SG_LOG(SG_SOUND,SG_INFO,
                    "  Unknown volume type, default to 'lin'");
       }
 
       volume.offset = kids[i]->getDoubleValue("offset", 0.0);
 
       if ((volume.min = kids[i]->getDoubleValue("min", 0.0)) < 0.0)
-         SG_LOG( SG_GENERAL, SG_WARN,
+         SG_LOG( SG_SOUND, SG_WARN,
           "Volume minimum value below 0. Forced to 0.");
 
       volume.max = kids[i]->getDoubleValue("max", 0.0);
       if (volume.max && (volume.max < volume.min) )
-         SG_LOG(SG_GENERAL,SG_ALERT,
+         SG_LOG(SG_SOUND,SG_ALERT,
                 "  Volume maximum below minimum. Neglected.");
 
       _volume.push_back(volume);
@@ -218,19 +219,19 @@
             }
 
          if (!pitch.fn)
-            SG_LOG(SG_GENERAL,SG_INFO,
+            SG_LOG(SG_SOUND,SG_INFO,
                    "  Unknown pitch type, default to 'lin'");
       }
      
       pitch.offset = kids[i]->getDoubleValue("offset", 1.0);
 
       if ((pitch.min = kids[i]->getDoubleValue("min", 0.0)) < 0.0)
-         SG_LOG(SG_GENERAL,SG_WARN,
+         SG_LOG(SG_SOUND,SG_WARN,
                 "  Pitch minimum value below 0. Forced to 0.");
 
       pitch.max = kids[i]->getDoubleValue("max", 0.0);
       if (pitch.max && (pitch.max < pitch.min) )
-         SG_LOG(SG_GENERAL,SG_ALERT,
+         SG_LOG(SG_SOUND,SG_ALERT,
                 "  Pitch maximum below minimum. Neglected");
 
       _pitch.push_back(pitch);
@@ -325,7 +326,7 @@
        if ((_mode != SGXmlSound::IN_TRANSIT) || (_stopping > MAX_TRANSIT_TIME))
        {
            if (_sample->is_playing()) {
-               SG_LOG(SG_GENERAL, SG_DEBUG, "Stopping audio after " << _dt_play
+               SG_LOG(SG_SOUND, SG_DEBUG, "Stopping audio after " << _dt_play
                       << " sec: " << _name );
 
                _sample->stop();
@@ -446,7 +447,7 @@
 
    double vol = volume_offset + volume;
    if (vol > 1.0) {
-      SG_LOG(SG_GENERAL, SG_DEBUG, "Sound volume too large for '"
+      SG_LOG(SG_SOUND, SG_DEBUG, "Sound volume too large for '"
               << _name << "':  " << vol << "  ->  clipping to 1.0");
       vol = 1.0;
    }
@@ -465,9 +466,9 @@
       else
          _sample->play(true);
 
-      SG_LOG(SG_GENERAL, SG_DEBUG, "Playing audio after " << _dt_stop 
+      SG_LOG(SG_SOUND, SG_DEBUG, "Playing audio after " << _dt_stop
                                    << " sec: " << _name);
-      SG_LOG(SG_GENERAL, SG_DEBUG,
+      SG_LOG(SG_SOUND, SG_DEBUG,
                          "Playing " << ((_mode == ONCE) ? "once" : "looped"));
 
       _active = true;

Modified: simgear/trunk/simgear/sound/xmlsound.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/sound/xmlsound.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/sound/xmlsound.hxx (original)
+++ simgear/trunk/simgear/sound/xmlsound.hxx Sun Jul 15 09:07:01 2012
@@ -36,7 +36,8 @@
 #include <vector>
 
 #include <simgear/compiler.h>
-#include <simgear/props/condition.hxx>
+
+#include <simgear/props/propsfwd.hxx>
 
 #include "sample_group.hxx"
 #include "sample_openal.hxx"

Modified: simgear/trunk/simgear/structure/SGAtomic.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/SGAtomic.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/SGAtomic.cxx (original)
+++ simgear/trunk/simgear/structure/SGAtomic.cxx Sun Jul 15 09:07:01 2012
@@ -1,6 +1,6 @@
 /* -*-c++-*-
  *
- * Copyright (C) 2005-2009 Mathias Froehlich 
+ * Copyright (C) 2005-2009,2011 Mathias Froehlich 
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -18,58 +18,105 @@
  *
  */
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
 #include "SGAtomic.hxx"
 
-#if defined(SGATOMIC_USE_GCC4_BUILTINS) && defined (__i386__)
+#if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
 
-// Usually the appropriate functions are inlined by gcc.
-// But if gcc is called with something equivalent to -march=i386,
-// it will not assume that there is a lock instruction and instead
-// calls this pair of functions. We will provide them here in this case.
-// Note that this assembler code will not work on a i386 chip anymore.
-// But I firmly believe that we can assume to run at least on a i486 ...
+#if defined(_WIN32)
+# include <windows.h>
+#elif defined(GCC_ATOMIC_BUILTINS_FOUND)
+#elif defined(__GNUC__) && defined(__i386__)
+#elif defined(SGATOMIC_USE_MUTEX)
+# include <simgear/threads/SGGuard.hxx>
+#else
+# error
+#endif
 
-extern "C" {
-
-unsigned __sync_sub_and_fetch_4(volatile void *ptr, unsigned value)
+unsigned
+SGAtomic::operator++()
 {
-  register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(ptr);
-  register unsigned result;
-  __asm__ __volatile__("lock; xadd{l} {%0,%1|%1,%0}"
-                       : "=r" (result), "=m" (*mem)
-                       : "0" (-value), "m" (*mem)
-                       : "memory");
-  return result - value;
+#if defined(_WIN32)
+    return InterlockedIncrement(reinterpret_cast<long volatile*>(&mValue));
+#elif defined(GCC_ATOMIC_BUILTINS_FOUND)
+    return __sync_add_and_fetch(&mValue, 1);
+#elif defined(__GNUC__) && defined(__i386__)
+    register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(&mValue);
+    register unsigned result;
+    __asm__ __volatile__("lock; xadd{l} {%0,%1|%1,%0}"
+                         : "=r" (result), "=m" (*mem)
+                         : "0" (1), "m" (*mem)
+                         : "memory");
+    return result + 1;
+#else
+    SGGuard<SGMutex> lock(mMutex);
+    return ++mValue;
+#endif
 }
 
-unsigned __sync_add_and_fetch_4(volatile void *ptr, unsigned value)
+unsigned
+SGAtomic::operator--()
 {
-  register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(ptr);
-  register unsigned result;
-  __asm__ __volatile__("lock; xadd{l} {%0,%1|%1,%0}"
-                       : "=r" (result), "=m" (*mem)
-                       : "0" (value), "m" (*mem)
-                       : "memory");
-  return result + value;
+#if defined(_WIN32)
+    return InterlockedDecrement(reinterpret_cast<long volatile*>(&mValue));
+#elif defined(GCC_ATOMIC_BUILTINS_FOUND)
+    return __sync_sub_and_fetch(&mValue, 1);
+#elif defined(__GNUC__) && defined(__i386__)
+    register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(&mValue);
+    register unsigned result;
+    __asm__ __volatile__("lock; xadd{l} {%0,%1|%1,%0}"
+                         : "=r" (result), "=m" (*mem)
+                         : "0" (-1), "m" (*mem)
+                         : "memory");
+    return result - 1;
+#else
+    SGGuard<SGMutex> lock(mMutex);
+    return --mValue;
+#endif
 }
 
-unsigned __sync_bool_compare_and_swap_4(volatile void *ptr,
-                                        unsigned oldValue, unsigned newValue)
+SGAtomic::operator unsigned() const
 {
-  register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(ptr);
-  unsigned before;
-  __asm__ __volatile__("lock; cmpxchg{l} {%1,%2|%1,%2}"
-                       : "=a"(before)
-                       : "q"(newValue), "m"(*mem), "0"(oldValue)
-                       : "memory");
-  return before == oldValue;
+#if defined(_WIN32)
+    return static_cast<unsigned const volatile &>(mValue);
+#elif defined(GCC_ATOMIC_BUILTINS_FOUND)
+    __sync_synchronize();
+    return mValue;
+#elif defined(__GNUC__) && defined(__i386__)
+    __asm__ __volatile__("": : : "memory");
+    return mValue;
+#else
+    SGGuard<SGMutex> lock(mMutex);
+    return mValue;
+#endif
 }
 
-void __sync_synchronize()
+bool
+SGAtomic::compareAndExchange(unsigned oldValue, unsigned newValue)
 {
-  __asm__ __volatile__("": : : "memory");
+#if defined(_WIN32)
+    long volatile* lvPtr = reinterpret_cast<long volatile*>(&mValue);
+    return oldValue == InterlockedCompareExchange(lvPtr, newValue, oldValue);
+#elif defined(GCC_ATOMIC_BUILTINS_FOUND)
+    return __sync_bool_compare_and_swap(&mValue, oldValue, newValue);
+#elif defined(__GNUC__) && defined(__i386__)
+    register volatile unsigned* mem = reinterpret_cast<volatile unsigned*>(&mValue);
+    unsigned before;
+    __asm__ __volatile__("lock; cmpxchg{l} {%1,%2|%1,%2}"
+                         : "=a"(before)
+                         : "q"(newValue), "m"(*mem), "0"(oldValue)
+                         : "memory");
+    return before == oldValue;
+#else
+    SGGuard<SGMutex> lock(mMutex);
+    if (mValue != oldValue)
+        return false;
+    mValue = newValue;
+    return true;
+#endif
 }
 
-} // extern "C"
-
 #endif

Modified: simgear/trunk/simgear/structure/SGAtomic.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/SGAtomic.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/SGAtomic.hxx (original)
+++ simgear/trunk/simgear/structure/SGAtomic.hxx Sun Jul 15 09:07:01 2012
@@ -1,6 +1,6 @@
 /* -*-c++-*-
  *
- * Copyright (C) 2005-2009 Mathias Froehlich 
+ * Copyright (C) 2005-2009,2011 Mathias Froehlich 
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -21,93 +21,96 @@
 #ifndef SGAtomic_HXX
 #define SGAtomic_HXX
 
-#if defined(__GNUC__) && ((4 < __GNUC__)||(4 == __GNUC__ && 1 <= __GNUC_MINOR__)) \
-  && (defined(__i386__) || defined(__x86_64__))
+#if defined(__GNUC__) && ((4 < __GNUC__)||(4 == __GNUC__ && 1 <= __GNUC_MINOR__)) && \
+    defined(__x86_64__)
 // No need to include something. Is a Compiler API ...
 # define SGATOMIC_USE_GCC4_BUILTINS
+#elif defined(__GNUC__) && defined(__i386__)
+# define SGATOMIC_USE_LIBRARY_FUNCTIONS
 #elif defined(__sgi) && defined(_COMPILER_VERSION) && (_COMPILER_VERSION>=730)
 // No need to include something. Is a Compiler API ...
 # define SGATOMIC_USE_MIPSPRO_BUILTINS
 #elif defined(_WIN32)
-# include <windows.h>
-# define SGATOMIC_USE_WIN32_INTERLOCKED
+# define SGATOMIC_USE_LIBRARY_FUNCTIONS
 #else
 // The sledge hammer ...
+# define SGATOMIC_USE_LIBRARY_FUNCTIONS
+# define SGATOMIC_USE_MUTEX
 # include <simgear/threads/SGThread.hxx>
-# include <simgear/threads/SGGuard.hxx>
 #endif
 
 class SGAtomic {
 public:
   SGAtomic(unsigned value = 0) : mValue(value)
   { }
+
+#if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
+  unsigned operator++();
+#else
   unsigned operator++()
   {
-#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+# if defined(SGATOMIC_USE_GCC4_BUILTINS)
     return __sync_add_and_fetch(&mValue, 1);
-#elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
+# elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
     return __add_and_fetch(&mValue, 1);
-#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
-    return InterlockedIncrement(reinterpret_cast<long volatile*>(&mValue));
+# else
+#  error
+# endif
+  }
+#endif
+
+#if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
+  unsigned operator--();
 #else
-    SGGuard<SGMutex> lock(mMutex);
-    return ++mValue;
-#endif
-  }
   unsigned operator--()
   {
-#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+# if defined(SGATOMIC_USE_GCC4_BUILTINS)
     return __sync_sub_and_fetch(&mValue, 1);
-#elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
+# elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
     return __sub_and_fetch(&mValue, 1);
-#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
-    return InterlockedDecrement(reinterpret_cast<long volatile*>(&mValue));
+# else
+#  error
+# endif
+  }
+#endif
+
+#if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
+  operator unsigned() const;
 #else
-    SGGuard<SGMutex> lock(mMutex);
-    return --mValue;
-#endif
-  }
   operator unsigned() const
   {
-#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+# if defined(SGATOMIC_USE_GCC4_BUILTINS)
     __sync_synchronize();
     return mValue;
-#elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
+# elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
     __synchronize();
     return mValue;
-#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
-    return static_cast<unsigned const volatile &>(mValue);
+# else
+#  error
+# endif
+  }
+#endif
+
+#if defined(SGATOMIC_USE_LIBRARY_FUNCTIONS)
+  bool compareAndExchange(unsigned oldValue, unsigned newValue);
 #else
-    SGGuard<SGMutex> lock(mMutex);
-    return mValue;
-#endif
-  }
-
   bool compareAndExchange(unsigned oldValue, unsigned newValue)
   {
-#if defined(SGATOMIC_USE_GCC4_BUILTINS)
+# if defined(SGATOMIC_USE_GCC4_BUILTINS)
     return __sync_bool_compare_and_swap(&mValue, oldValue, newValue);
-#elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
+# elif defined(SGATOMIC_USE_MIPOSPRO_BUILTINS)
     return __compare_and_swap(&mValue, oldValue, newValue);
-#elif defined(SGATOMIC_USE_WIN32_INTERLOCKED)
-    long volatile* lvPtr = reinterpret_cast<long volatile*>(&mValue);
-    return oldValue == InterlockedCompareExchange(lvPtr, newValue, oldValue);
-#else
-    SGGuard<SGMutex> lock(mMutex);
-    if (mValue != oldValue)
-      return false;
-    mValue = newValue;
-    return true;
+# else
+#  error
+# endif
+  }
 #endif
-  }
 
 private:
   SGAtomic(const SGAtomic&);
   SGAtomic& operator=(const SGAtomic&);
 
-#if !defined(SGATOMIC_USE_GCC4_BUILTINS) \
-  && !defined(SGATOMIC_USE_MIPOSPRO_BUILTINS) \
-  && !defined(SGATOMIC_USE_WIN32_INTERLOCKED)
+#if defined(SGATOMIC_USE_MUTEX)
   mutable SGMutex mMutex;
 #endif
   unsigned mValue;

Modified: simgear/trunk/simgear/structure/SGExpression.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/SGExpression.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/SGExpression.hxx (original)
+++ simgear/trunk/simgear/structure/SGExpression.hxx Sun Jul 15 09:07:01 2012
@@ -1248,7 +1248,7 @@
     ConvertExpression() {}
     ConvertExpression(::SGExpression<OpType>* expr0)
     {
-      addOperand(expr0);
+      this->addOperand(expr0);
     }
     virtual void eval(T& value, const simgear::expression::Binding* b) const
     {

Modified: simgear/trunk/simgear/structure/SGSmplhist.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/SGSmplhist.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/SGSmplhist.cxx (original)
+++ simgear/trunk/simgear/structure/SGSmplhist.cxx Sun Jul 15 09:07:01 2012
@@ -15,9 +15,11 @@
 License along with this library; if not, write to the Free Software
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
-#ifdef __GNUG__
-#pragma implementation
+
+#ifdef HAVE_CONFIG_H
+#include <simgear_config.h>
 #endif
+
 #include <iostream>
 #include <fstream>
 #include "SGSmplhist.hxx"
@@ -94,7 +96,7 @@
   return (0);
 }
 
-void SampleHistogram::printBuckets (ostream & s)
+void SampleHistogram::printBuckets (std::ostream & s)
 {
   for (int i = 0; i < howManyBuckets; i++)
     {

Modified: simgear/trunk/simgear/structure/SGSmplhist.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/SGSmplhist.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/SGSmplhist.hxx (original)
+++ simgear/trunk/simgear/structure/SGSmplhist.hxx Sun Jul 15 09:07:01 2012
@@ -16,13 +16,7 @@
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
-#ifdef HAVE_CONFIG_H
-#include <simgear_config.h>
-#endif
 #ifndef SampleHistogram_h
-#ifdef __GNUG__
-#pragma interface
-#endif
 #define SampleHistogram_h 1
 
 #include <iosfwd>
@@ -61,7 +55,7 @@
 inline int SampleHistogram::buckets ()
 {
   return (howManyBuckets);
-};
+}
 
 inline double SampleHistogram::bucketThreshold (int i)
 {

Modified: simgear/trunk/simgear/structure/SGSmplstat.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/SGSmplstat.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/SGSmplstat.cxx (original)
+++ simgear/trunk/simgear/structure/SGSmplstat.cxx Sun Jul 15 09:07:01 2012
@@ -15,9 +15,6 @@
 License along with this library; if not, write to the Free Software
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
-#ifdef __GNUG__
-#pragma implementation
-#endif
 
 #include <math.h>
 
@@ -84,6 +81,7 @@
 {
   n += 1;
   x += value;
+  allTimeTotal += value;
   x2 += (value * value);
   if (minValue > value)
     minValue = value;

Modified: simgear/trunk/simgear/structure/SGSmplstat.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/SGSmplstat.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/SGSmplstat.hxx (original)
+++ simgear/trunk/simgear/structure/SGSmplstat.hxx Sun Jul 15 09:07:01 2012
@@ -16,16 +16,12 @@
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 #ifndef SampleStatistic_h
-#ifdef __GNUG__
-#pragma interface
-#endif
+
 #define SampleStatistic_h 1
 
 
 #undef min
 #undef max
-
-using namespace std;
 
 class SampleStatistic
 {
@@ -34,6 +30,7 @@
   double x;
   double x2;
   double minValue, maxValue;
+  double allTimeTotal;
 
 public:  SampleStatistic ();
   inline virtual ~ SampleStatistic ();
@@ -46,6 +43,7 @@
   double var () const;
   double min () const;
   double max () const;
+  double total () const;
   double confidence (int p_percentage) const;
   double confidence (double p_value) const;
 
@@ -62,6 +60,7 @@
 
 inline SampleStatistic::SampleStatistic ()
 {
+  allTimeTotal = 0;
   reset ();
 }
 inline int SampleStatistic::samples () const
@@ -76,6 +75,10 @@
 {
   return (maxValue);
 }
+inline double SampleStatistic::total () const
+{
+  return (allTimeTotal);
+}
 
 inline SampleStatistic::~SampleStatistic ()
 {

Modified: simgear/trunk/simgear/structure/Singleton.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/Singleton.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/Singleton.hxx (original)
+++ simgear/trunk/simgear/structure/Singleton.hxx Sun Jul 15 09:07:01 2012
@@ -1,10 +1,12 @@
 #ifndef SIMGEAR_SINGLETON_HXX
 #define SIMGEAR_SINGLETON_HXX 1
 
-#include <boost/pool/detail/singleton.hpp>
+#include "singleton.hpp"
 
+#ifndef NO_OPENSCENEGRAPH_INTERFACE
 #include <osg/Referenced>
 #include <osg/ref_ptr>
+#endif
 
 namespace simgear
 {
@@ -27,6 +29,7 @@
     }
 };
 
+#ifndef NO_OPENSCENEGRAPH_INTERFACE
 template <typename RefClass>
 class SingletonRefPtr
 {
@@ -54,5 +57,7 @@
         return SingletonRefPtr<RefClass>::instance();
     }
 };
+#endif // of NO_OPENSCENEGRAPH_INTERFACE
+
 }
 #endif

Modified: simgear/trunk/simgear/structure/StringTable.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/StringTable.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/StringTable.cxx (original)
+++ simgear/trunk/simgear/structure/StringTable.cxx Sun Jul 15 09:07:01 2012
@@ -1,6 +1,6 @@
 #include "StringTable.hxx"
 
-#include <OpenThreads/ScopedLock>
+#include <simgear/threads/SGGuard.hxx>
 
 namespace simgear
 {
@@ -8,8 +8,7 @@
 
 const string* StringTable::insert(const string& str)
 {
-    using namespace OpenThreads;
-    ScopedLock<Mutex> lock(_mutex);
+    SGGuard<SGMutex> lock(_mutex);
     StringContainer::iterator it = _strings.insert(str).first;
     return &*it;
 }

Modified: simgear/trunk/simgear/structure/StringTable.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/StringTable.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/StringTable.hxx (original)
+++ simgear/trunk/simgear/structure/StringTable.hxx Sun Jul 15 09:07:01 2012
@@ -3,7 +3,7 @@
 
 #include <string>
 
-#include <OpenThreads/Mutex>
+#include <simgear/threads/SGThread.hxx>
 #include <boost/multi_index_container.hpp>
 #include <boost/multi_index/hashed_index.hpp>
 #include <boost/multi_index/identity.hpp>
@@ -21,7 +21,7 @@
 {
     const std::string* insert(const std::string& str);
 private:
-    OpenThreads::Mutex _mutex;
+    SGMutex _mutex;
     StringContainer _strings;
 };
 }

Modified: simgear/trunk/simgear/structure/commands.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/commands.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/commands.cxx (original)
+++ simgear/trunk/simgear/structure/commands.cxx Sun Jul 15 09:07:01 2012
@@ -11,13 +11,12 @@
 #include <memory>
 #include <simgear/props/props_io.hxx>
 
-#include <OpenThreads/Mutex>
-#include <OpenThreads/ScopedLock>
-
 #include "commands.hxx"
 
 #include <simgear/math/SGMath.hxx>
 #include <simgear/structure/exception.hxx>
+#include <simgear/threads/SGThread.hxx>
+#include <simgear/threads/SGGuard.hxx>
 #include <simgear/debug/logstream.hxx>
 
 
@@ -36,7 +35,7 @@
   // no-op
 }
 
-OpenThreads::Mutex SGCommandMgr::_instanceMutex;
+SGMutex SGCommandMgr::_instanceMutex;
 
 SGCommandMgr*
 SGCommandMgr::instance()
@@ -45,7 +44,7 @@
   if (mgr.get())
     return mgr.get();
 
-  OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_instanceMutex);
+  SGGuard<SGMutex> lock(_instanceMutex);
   if (mgr.get())
     return mgr.get();
 
@@ -85,8 +84,8 @@
   command_t command = getCommand(name);
   if (command == 0)
     return false;
-  
-  
+
+
   try {
     return (*command)(arg);
   } catch (sg_exception& e) {

Modified: simgear/trunk/simgear/structure/commands.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/commands.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/commands.hxx (original)
+++ simgear/trunk/simgear/structure/commands.hxx Sun Jul 15 09:07:01 2012
@@ -17,8 +17,7 @@
 #include <map>
 #include <vector>
 
-#include <OpenThreads/Mutex>
-
+#include <simgear/threads/SGThread.hxx>
 #include <simgear/math/sg_types.hxx>
 #include <simgear/props/props.hxx>
 
@@ -107,7 +106,7 @@
   typedef std::map<std::string,command_t> command_map;
   command_map _commands;
 
-  static OpenThreads::Mutex _instanceMutex;
+  static SGMutex _instanceMutex;
 
 };
 

Modified: simgear/trunk/simgear/structure/event_mgr.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/event_mgr.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/event_mgr.cxx (original)
+++ simgear/trunk/simgear/structure/event_mgr.cxx Sun Jul 15 09:07:01 2012
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
 #include "event_mgr.hxx"
 
 #include <simgear/math/SGMath.hxx>

Modified: simgear/trunk/simgear/structure/subsystem_mgr.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/subsystem_mgr.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/subsystem_mgr.cxx (original)
+++ simgear/trunk/simgear/structure/subsystem_mgr.cxx Sun Jul 15 09:07:01 2012
@@ -18,6 +18,10 @@
 //
 // $Id$
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
 #include <simgear/debug/logstream.hxx>
 #include <simgear/timing/timestamp.hxx>
 
@@ -25,13 +29,16 @@
 #include "subsystem_mgr.hxx"
 
 #include <simgear/math/SGMath.hxx>
-
-
-const int SG_MAX_SUBSYSTEM_EXCEPTIONS = 4;
+#include "SGSmplstat.hxx"
+
+const int SG_MAX_SUBSYSTEM_EXCEPTIONS = 4;
+
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGSubsystem
 ////////////////////////////////////////////////////////////////////////
 
+SGSubsystemTimingCb SGSubsystem::reportTimingCb = NULL;
+void* SGSubsystem::reportTimingUserData = NULL;
 
 SGSubsystem::SGSubsystem ()
   : _suspended(false)
@@ -96,28 +103,6 @@
   return _suspended;
 }
 
-
-void
-SGSubsystem::printTimingInformation ()
-{
-   SGTimeStamp startTime;
-   for ( eventTimeVecIterator i = timingInfo.begin();
-          i != timingInfo.end();
-          ++i) {
-       if (i == timingInfo.begin()) {
-           startTime = i->getTime();
-       } else {
-           SGTimeStamp endTime = i->getTime();
-           SG_LOG(SG_GENERAL, SG_ALERT, "- Getting to timestamp :   "
-                  << i->getName() << " takes " << endTime - startTime
-                  << " sec.");
-	   startTime = endTime;
-       }
-   }
-}
-
-
-
 void SGSubsystem::stamp(const string& name)
 {
     timingInfo.push_back(TimingInfo(name, SGTimeStamp::now()));
@@ -127,6 +112,30 @@
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGSubsystemGroup.
 ////////////////////////////////////////////////////////////////////////
+
+class SGSubsystemGroup::Member
+{    
+private:
+    Member (const Member &member);
+public:
+    Member ();
+    virtual ~Member ();
+    
+    virtual void update (double delta_time_sec);
+
+    void reportTiming(void) { if (reportTimingCb) reportTimingCb(reportTimingUserData, name, &timeStat); }
+    void updateExecutionTime(double time) { timeStat += time;}
+
+    SampleStatistic timeStat;
+    std::string name;
+    SGSubsystem * subsystem;
+    double min_step_sec;
+    double elapsed_sec;
+    bool collectTimeStats;
+    int exceptionCount;
+};
+
+
 
 SGSubsystemGroup::SGSubsystemGroup () :
   _fixedUpdateTime(-1.0),
@@ -136,8 +145,6 @@
 
 SGSubsystemGroup::~SGSubsystemGroup ()
 {
-    printTimingStatistics();
-
     // reverse order to prevent order dependency problems
     for (unsigned int i = _members.size(); i > 0; i--)
     {
@@ -203,38 +210,31 @@
       delta_time_sec = _fixedUpdateTime;
     }
 
+    SGTimeStamp timeStamp;
     while (loopCount-- > 0) {
       for (unsigned int i = 0; i < _members.size(); i++)
       {
-           SGTimeStamp timeStamp = SGTimeStamp::now();
-           _members[i]->update(delta_time_sec); // indirect call
-           timeStamp = SGTimeStamp::now() - timeStamp;
-           double b = timeStamp.toUSecs();
-           _members[i]->updateExecutionTime(b);
-           double threshold = _members[i]->getTimeWarningThreshold();
-           if (( b > threshold ) && (b > 10000)) {
-               _members[i]->printTimingInformation(b);
-           }
+          bool recordTime = (reportTimingCb != NULL);
+          if (recordTime)
+              timeStamp = SGTimeStamp::now();
+
+          _members[i]->update(delta_time_sec); // indirect call
+
+          if ((recordTime)&&(reportTimingCb))
+          {
+              timeStamp = SGTimeStamp::now() - timeStamp;
+              _members[i]->updateExecutionTime(timeStamp.toUSecs());
+          }
       }
     } // of multiple update loop
 }
 
-void 
-SGSubsystemGroup::collectDebugTiming(bool collect)
-{
-    for (unsigned int i = 0; i < _members.size(); i++)
-    {
-        _members[i]->collectDebugTiming(collect);
-    }
-}
-
-void 
-SGSubsystemGroup::printTimingStatistics(double minMaxTime,double minJitter)
+void
+SGSubsystemGroup::reportTiming(void)
 {
     for (unsigned int i = _members.size(); i > 0; i--)
     {
-        _members[i-1]->printTimingStatistics(minMaxTime, minJitter);
-        _members[i-1]->timeStat.reset();
+        _members[i-1]->reportTiming();
     }
 }
 
@@ -297,35 +297,6 @@
   _fixedUpdateTime = dt;
 }
 
-/**
- * Print timing statistics.
- * Only show data if jitter exceeds minJitter or
- * maximum time exceeds minMaxTime. 
- */
-void
-SGSubsystemGroup::Member::printTimingStatistics(double minMaxTime,double minJitter)
-{
-    if (collectTimeStats) {
-        double minTime = timeStat.min()   / 1000;
-        double maxTime = timeStat.max()   / 1000;
-        double meanTime = timeStat.mean() / 1000;
-        double stddev   = timeStat.stdDev()   / 1000;
-
-        if ((maxTime - minTime >= minJitter)||
-            (maxTime >= minMaxTime))
-        {
-            char buffer[256];
-            snprintf(buffer, 256, "Timing summary for %20s.\n"
-                                  "-  mean time: %04.2f ms.\n"
-                                  "-  min time : %04.2f ms.\n"
-                                  "-  max time : %04.2f ms.\n"
-                                  "-  stddev   : %04.2f ms.\n", name.c_str(), meanTime, minTime, maxTime, stddev);
-            SG_LOG(SG_GENERAL, SG_ALERT, buffer);
-        }
-    }
-}
-
-
 bool
 SGSubsystemGroup::has_subsystem (const string &name) const
 {
@@ -360,7 +331,6 @@
       subsystem(0),
       min_step_sec(0),
       elapsed_sec(0),
-      collectTimeStats(false),
       exceptionCount(0)
 {
 }
@@ -403,31 +373,6 @@
 }
 
 
-void 
-SGSubsystemGroup::Member::printTimingInformation(double time)
-{
-     if (collectTimeStats) {
-         SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem Timing Alert, subsystem \"" << name << "\": " << time/1000.0 << "ms");
-         subsystem->printTimingInformation();
-     }
-}
-
-double SGSubsystemGroup::Member::getTimeWarningThreshold()
-{
-    return (timeStat.mean() + 3 * timeStat.stdDev());
-}
-
-void SGSubsystemGroup::Member::updateExecutionTime(double time)
-{
-    if (collectTimeStats) {
-        timeStat += time;
-    }
-}
-
-
-
-
-
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGSubsystemMgr.
 ////////////////////////////////////////////////////////////////////////
@@ -501,14 +446,6 @@
 {
     for (int i = 0; i < MAX_GROUPS; i++) {
         _groups[i]->update(delta_time_sec);
-    }
-}
-
-void 
-SGSubsystemMgr::collectDebugTiming(bool collect)
-{
-    for (int i = 0; i < MAX_GROUPS; i++) {
-        _groups[i]->collectDebugTiming(collect);
     }
 }
 
@@ -586,11 +523,12 @@
         return s->second;
 }
 
-void
-SGSubsystemMgr::printTimingStatistics(double minMaxTime,double minJitter)
+/** Trigger the timing callback to report data for all subsystems. */
+void
+SGSubsystemMgr::reportTiming()
 {
     for (int i = 0; i < MAX_GROUPS; i++) {
-        _groups[i]->printTimingStatistics(minMaxTime, minJitter);
+        _groups[i]->reportTiming();
     } // of groups iteration
 }
 

Modified: simgear/trunk/simgear/structure/subsystem_mgr.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/structure/subsystem_mgr.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/structure/subsystem_mgr.hxx (original)
+++ simgear/trunk/simgear/structure/subsystem_mgr.hxx Sun Jul 15 09:07:01 2012
@@ -1,3 +1,4 @@
+
 // Written by David Megginson, started 2000-12
 //
 // Copyright (C) 2000  David Megginson, david at megginson.com
@@ -31,7 +32,6 @@
 
 #include <simgear/timing/timestamp.hxx>
 #include <simgear/structure/SGSharedPtr.hxx>
-#include "SGSmplstat.hxx"
 
 
 class TimingInfo
@@ -48,9 +48,12 @@
     const SGTimeStamp& getTime() const { return time; }
 };
 
+class SampleStatistic;
+
 typedef std::vector<TimingInfo> eventTimeVec;
 typedef std::vector<TimingInfo>::iterator eventTimeVecIterator;
 
+typedef void (*SGSubsystemTimingCb)(void* userData, const std::string& name, SampleStatistic* pStatistic);
 
 
 /**
@@ -227,7 +230,7 @@
 
 
   /**
-   * Suspend or resum operation of this subsystem.
+   * Suspend or resume operation of this subsystem.
    *
    * @param suspended true if the subsystem should be suspended, false
    * otherwise.
@@ -253,43 +256,25 @@
    */
   virtual bool is_suspended () const;
 
-
-  /**
-   * Keep track of execution time.
-   *
-   * <p>This method keeps track of timing statistics for each subsystem.</p>
-   * 
-   * @param time execution time in ms of last call.
-   */
-  void updateExecutionTime(double time);
-
-  /**
-   * Print details of execution time.
-   *
-   * <p>For debugging purposes, developers can place stamp() calls
-   * at strategic points in the update() function of each subsystem, which 
-   * record the time between the successive calls to stamp. This method,
-   * printExecutionTime() is called after exectution of the subsystem
-   * update function itself to conduct a post-hoc analysis of excecution
-   * time</p>
-   */ 
-  void printTimingInformation();
+  /**
+   * Trigger the callback to report timing information for all subsystems.
+   */
+  void reportTiming(void);
 
   /**
    * Place time stamps at strategic points in the execution of subsystems 
    * update() member functions. Predominantly for debugging purposes.
    */
   void stamp(const std::string& name);
-  
-
 
 protected:
 
   bool _suspended;
 
   eventTimeVec timingInfo;
-  //int test;
-
+
+  static SGSubsystemTimingCb reportTimingCb;
+  static void* reportTimingUserData;
 };
 
 
@@ -322,40 +307,16 @@
     virtual void remove_subsystem (const std::string &name);
     virtual bool has_subsystem (const std::string &name) const;
 
-    void collectDebugTiming(bool collect);
-    void printTimingStatistics(double minMaxTime=0.0,double minJitter=0.0);
+    void reportTiming(void);
 
     /**
-     * 
+     *
      */
     void set_fixed_update_time(double fixed_dt);
 private:
 
-    class Member {
-
-    private:
-        Member (const Member &member);
-    public:
-        Member ();
-        virtual ~Member ();
-
-        virtual void update (double delta_time_sec);
-        void printTimingInformation(double time);
-        void printTimingStatistics(double minMaxTime=0.0,double minJitter=0.0);
-        void updateExecutionTime(double time);
-        double getTimeWarningThreshold();
-        void collectDebugTiming (bool collect) { collectTimeStats = collect; };
-
-        SampleStatistic timeStat;
-        std::string name;
-        SGSubsystem * subsystem;
-        double min_step_sec;
-        double elapsed_sec;
-        bool collectTimeStats;
-        int exceptionCount;
-    };
-
-    Member * get_member (const std::string &name, bool create = false);
+    class Member;
+    Member* get_member (const std::string &name, bool create = false);
 
     std::vector<Member *> _members;
     
@@ -392,9 +353,10 @@
     enum GroupType {
         INIT = 0,
         GENERAL,
-        FDM,  ///< flight model, autopilot, instruments that run coupled
+        FDM,        ///< flight model, autopilot, instruments that run coupled
         POST_FDM,   ///< certain subsystems depend on FDM data
         DISPLAY,    ///< view, camera, rendering updates
+        SOUND/*I want to be last!*/,  ///< needs to run AFTER display, to allow concurrent GPU/sound processing
         MAX_GROUPS
     };
 
@@ -427,16 +389,14 @@
 
     virtual SGSubsystem * get_subsystem(const std::string &name) const;
 
-   void collectDebugTiming(bool collect);
-   void printTimingStatistics(double minMaxTime=0.0,double minJitter=0.0);
+    void reportTiming();
+    void setReportTimingCb(void* userData,SGSubsystemTimingCb cb) {reportTimingCb = cb;reportTimingUserData = userData;}
 
 private:
-
     SGSubsystemGroup* _groups[MAX_GROUPS];
-    
+
     typedef std::map<std::string, SGSubsystem*> SubsystemDict;
     SubsystemDict _subsystem_map;
-
 };
 
 

Modified: simgear/trunk/simgear/threads/SGQueue.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/threads/SGQueue.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/threads/SGQueue.hxx (original)
+++ simgear/trunk/simgear/threads/SGQueue.hxx Sun Jul 15 09:07:01 2012
@@ -5,9 +5,8 @@
 
 #include <cassert>
 #include <queue>
-#include <OpenThreads/Mutex>
-#include <OpenThreads/ScopedLock>
-#include <OpenThreads/Condition>
+#include "SGGuard.hxx"
+#include "SGThread.hxx"
 
 /**
  * SGQueue defines an interface for a FIFO.
@@ -66,7 +65,7 @@
 
 protected:
     /**
-     * 
+     *
      */
     std::queue<T> fifo;
 };
@@ -74,7 +73,7 @@
 /**
  * A simple thread safe queue.  All access functions are guarded with a mutex.
  */
-template<class T, class SGLOCK=OpenThreads::Mutex>
+template<class T>
 class SGLockedQueue : public SGQueue<T>
 {
 public:
@@ -95,7 +94,7 @@
      * @return bool True if queue is empty, otherwisr false.
      */
     virtual bool empty() {
-	OpenThreads::ScopedLock<SGLOCK> g(mutex);
+	SGGuard<SGMutex> g(mutex);
 	return this->fifo.empty();
     }
 
@@ -105,7 +104,7 @@
      * @param T object to add.
      */
     virtual void push( const T& item ) {
-	OpenThreads::ScopedLock<SGLOCK> g(mutex);
+	SGGuard<SGMutex> g(mutex);
 	this->fifo.push( item );
     }
 
@@ -115,7 +114,7 @@
      * @return T next available object.
      */
     virtual T front() {
-	OpenThreads::ScopedLock<SGLOCK> g(mutex);
+	SGGuard<SGMutex> g(mutex);
 	assert( ! this->fifo.empty() );
 	T item = this->fifo.front();
 	return item;
@@ -127,7 +126,7 @@
      * @return T next available object.
      */
     virtual T pop() {
-	OpenThreads::ScopedLock<SGLOCK> g(mutex);
+	SGGuard<SGMutex> g(mutex);
 	//if (fifo.empty()) throw NoSuchElementException();
 	assert( ! this->fifo.empty() );
 //  	if (fifo.empty())
@@ -146,7 +145,7 @@
      * @return size_t size of queue.
      */
     virtual size_t size() {
-	OpenThreads::ScopedLock<SGLOCK> g(mutex);
+	SGGuard<SGMutex> g(mutex);
         return this->fifo.size();
     }
 
@@ -155,7 +154,7 @@
     /**
      * Mutex to serialise access.
      */
-    SGLOCK mutex;
+    SGMutex mutex;
 
 private:
     // Prevent copying.
@@ -182,10 +181,10 @@
     ~SGBlockingQueue() {}
 
     /**
-     * 
+     *
      */
     virtual bool empty() {
-	OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+	SGGuard<SGMutex> g(mutex);
 	return this->fifo.empty();
     }
 
@@ -195,7 +194,7 @@
      * @param T object to add.
      */
     virtual void push( const T& item ) {
-	OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+	SGGuard<SGMutex> g(mutex);
 	this->fifo.push( item );
 	not_empty.signal();
     }
@@ -207,7 +206,7 @@
      * @return T next available object.
      */
     virtual T front() {
-	OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+	SGGuard<SGMutex> g(mutex);
 
 	assert(this->fifo.empty() != true);
 	//if (fifo.empty()) throw ??
@@ -223,10 +222,10 @@
      * @return T next available object.
      */
     virtual T pop() {
-	OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+	SGGuard<SGMutex> g(mutex);
 
 	while (this->fifo.empty())
-	    not_empty.wait(&mutex);
+	    not_empty.wait(mutex);
 
 	assert(this->fifo.empty() != true);
 	//if (fifo.empty()) throw ??
@@ -242,7 +241,7 @@
      * @return size_t size of queue.
      */
     virtual size_t size() {
-	OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+	SGGuard<SGMutex> g(mutex);
         return this->fifo.size();
     }
 
@@ -251,12 +250,12 @@
     /**
      * Mutex to serialise access.
      */
-    OpenThreads::Mutex mutex;
+    SGMutex mutex;
 
     /**
      * Condition to signal when queue not empty.
      */
-    OpenThreads::Condition not_empty;
+    SGWaitCondition not_empty;
 
 private:
     // Prevent copying.
@@ -284,18 +283,18 @@
     ~SGBlockingDeque() {}
 
     /**
-     * 
+     *
      */
     virtual void clear() {
-    OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+    SGGuard<SGMutex> g(mutex);
     this->queue.clear();
     }
-    
-    /**
-     * 
+
+    /**
+     *
      */
     virtual bool empty() {
-    OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+    SGGuard<SGMutex> g(mutex);
     return this->queue.empty();
     }
 
@@ -305,7 +304,7 @@
      * @param T object to add.
      */
     virtual void push_front( const T& item ) {
-    OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+    SGGuard<SGMutex> g(mutex);
     this->queue.push_front( item );
     not_empty.signal();
     }
@@ -316,7 +315,7 @@
      * @param T object to add.
      */
     virtual void push_back( const T& item ) {
-    OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+    SGGuard<SGMutex> g(mutex);
     this->queue.push_back( item );
     not_empty.signal();
     }
@@ -328,7 +327,7 @@
      * @return T next available object.
      */
     virtual T front() {
-    OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+    SGGuard<SGMutex> g(mutex);
 
     assert(this->queue.empty() != true);
     //if (queue.empty()) throw ??
@@ -344,10 +343,10 @@
      * @return T next available object.
      */
     virtual T pop_front() {
-    OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+    SGGuard<SGMutex> g(mutex);
 
     while (this->queue.empty())
-        not_empty.wait(&mutex);
+        not_empty.wait(mutex);
 
     assert(this->queue.empty() != true);
     //if (queue.empty()) throw ??
@@ -364,10 +363,10 @@
      * @return T next available object.
      */
     virtual T pop_back() {
-    OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+    SGGuard<SGMutex> g(mutex);
 
     while (this->queue.empty())
-        not_empty.wait(&mutex);
+        not_empty.wait(mutex);
 
     assert(this->queue.empty() != true);
     //if (queue.empty()) throw ??
@@ -383,7 +382,7 @@
      * @return size_t size of queue.
      */
     virtual size_t size() {
-    OpenThreads::ScopedLock<OpenThreads::Mutex> g(mutex);
+    SGGuard<SGMutex> g(mutex);
         return this->queue.size();
     }
 
@@ -392,12 +391,12 @@
     /**
      * Mutex to serialise access.
      */
-    OpenThreads::Mutex mutex;
+    SGMutex mutex;
 
     /**
      * Condition to signal when queue not empty.
      */
-    OpenThreads::Condition not_empty;
+    SGWaitCondition not_empty;
 
 private:
     // Prevent copying.

Modified: simgear/trunk/simgear/threads/SGThread.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/threads/SGThread.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/threads/SGThread.cxx (original)
+++ simgear/trunk/simgear/threads/SGThread.cxx Sun Jul 15 09:07:01 2012
@@ -1,107 +1,410 @@
+// SGThread - Simple pthread class wrappers.
+//
+// Written by Bernie Bright, started April 2001.
+//
+// Copyright (C) 2001  Bernard Bright - bbright at bigpond.net.au
+// Copyright (C) 2011  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
 #include <simgear/compiler.h>
 
-#if defined(_MSC_VER) || defined(__MINGW32__)
-#  include <time.h>
+#include "SGThread.hxx"
+
+#ifdef _WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+/// win32 threads
+/////////////////////////////////////////////////////////////////////////////
+
+#include <list>
+#include <windows.h>
+
+struct SGThread::PrivateData {
+    PrivateData() :
+        _handle(INVALID_HANDLE_VALUE)
+    {
+    }
+    ~PrivateData()
+    {
+        if (_handle == INVALID_HANDLE_VALUE)
+            return;
+        CloseHandle(_handle);
+        _handle = INVALID_HANDLE_VALUE;
+    }
+
+    static DWORD WINAPI start_routine(LPVOID data)
+    {
+        SGThread* thread = reinterpret_cast<SGThread*>(data);
+        thread->run();
+        return 0;
+    }
+
+    bool start(SGThread& thread)
+    {
+        if (_handle != INVALID_HANDLE_VALUE)
+            return false;
+        _handle = CreateThread(0, 0, start_routine, &thread, 0, 0);
+        if (_handle == INVALID_HANDLE_VALUE)
+            return false;
+        return true;
+    }
+
+    void join()
+    {
+        if (_handle == INVALID_HANDLE_VALUE)
+            return;
+        DWORD ret = WaitForSingleObject(_handle, INFINITE);
+        if (ret != WAIT_OBJECT_0)
+            return;
+        CloseHandle(_handle);
+        _handle = INVALID_HANDLE_VALUE;
+    }
+
+    HANDLE _handle;
+};
+
+struct SGMutex::PrivateData {
+    PrivateData()
+    {
+        InitializeCriticalSection((LPCRITICAL_SECTION)&_criticalSection);
+    }
+
+    ~PrivateData()
+    {
+        DeleteCriticalSection((LPCRITICAL_SECTION)&_criticalSection);
+    }
+
+    void lock(void)
+    {
+        EnterCriticalSection((LPCRITICAL_SECTION)&_criticalSection);
+    }
+
+    void unlock(void)
+    {
+        LeaveCriticalSection((LPCRITICAL_SECTION)&_criticalSection);
+    }
+
+    CRITICAL_SECTION _criticalSection;
+};
+
+struct SGWaitCondition::PrivateData {
+    ~PrivateData(void)
+    {
+        // The waiters list should be empty anyway
+        _mutex.lock();
+        while (!_pool.empty()) {
+            CloseHandle(_pool.front());
+            _pool.pop_front();
+        }
+        _mutex.unlock();
+    }
+
+    void signal(void)
+    {
+        _mutex.lock();
+        if (!_waiters.empty())
+            SetEvent(_waiters.back());
+        _mutex.unlock();
+    }
+
+    void broadcast(void)
+    {
+        _mutex.lock();
+        for (std::list<HANDLE>::iterator i = _waiters.begin(); i != _waiters.end(); ++i)
+            SetEvent(*i);
+        _mutex.unlock();
+    }
+
+    bool wait(SGMutex::PrivateData& externalMutex, DWORD msec)
+    {
+        _mutex.lock();
+        if (_pool.empty())
+            _waiters.push_front(CreateEvent(NULL, FALSE, FALSE, NULL));
+        else
+            _waiters.splice(_waiters.begin(), _pool, _pool.begin());
+        std::list<HANDLE>::iterator i = _waiters.begin();
+        _mutex.unlock();
+
+        externalMutex.unlock();
+
+        DWORD result = WaitForSingleObject(*i, msec);
+
+        externalMutex.lock();
+
+        _mutex.lock();
+        if (result != WAIT_OBJECT_0)
+            result = WaitForSingleObject(*i, 0);
+        _pool.splice(_pool.begin(), _waiters, i);
+        _mutex.unlock();
+
+        return result == WAIT_OBJECT_0;
+    }
+
+    void wait(SGMutex::PrivateData& externalMutex)
+    {
+        wait(externalMutex, INFINITE);
+    }
+
+    // Protect the list of waiters
+    SGMutex::PrivateData _mutex;
+
+    std::list<HANDLE> _waiters;
+    std::list<HANDLE> _pool;
+};
+
 #else
-#  if defined ( sgi ) && !defined( __GNUC__ )
-     // This works around a bug triggered when using MipsPro 7.4.1
-     // and (at least) IRIX 6.5.20
-#    include <iostream>
-#  endif
-#  include <sys/time.h>
+/////////////////////////////////////////////////////////////////////////////
+/// posix threads
+/////////////////////////////////////////////////////////////////////////////
+
+#include <pthread.h>
+#include <cassert>
+#include <cerrno>
+#include <sys/time.h>
+
+struct SGThread::PrivateData {
+    PrivateData() :
+        _started(false)
+    {
+    }
+    ~PrivateData()
+    {
+        // If we are still having a started thread and nobody waited,
+        // now detach ...
+        if (!_started)
+            return;
+        pthread_detach(_thread);
+    }
+
+    static void *start_routine(void* data)
+    {
+        SGThread* thread = reinterpret_cast<SGThread*>(data);
+        thread->run();
+        return 0;
+    }
+
+    bool start(SGThread& thread)
+    {
+        if (_started)
+            return false;
+
+        int ret = pthread_create(&_thread, 0, start_routine, &thread);
+        if (0 != ret)
+            return false;
+
+        _started = true;
+        return true;
+    }
+
+    void join()
+    {
+        if (!_started)
+            return;
+
+        pthread_join(_thread, 0);
+        _started = false;
+    }
+
+    pthread_t _thread;
+    bool _started;
+};
+
+struct SGMutex::PrivateData {
+    PrivateData()
+    {
+        int err = pthread_mutex_init(&_mutex, 0);
+        assert(err == 0);
+        (void)err;
+    }
+
+    ~PrivateData()
+    {
+        int err = pthread_mutex_destroy(&_mutex);
+        assert(err == 0);
+        (void)err;
+    }
+
+    void lock(void)
+    {
+        int err = pthread_mutex_lock(&_mutex);
+        assert(err == 0);
+        (void)err;
+    }
+
+    void unlock(void)
+    {
+        int err = pthread_mutex_unlock(&_mutex);
+        assert(err == 0);
+        (void)err;
+    }
+
+    pthread_mutex_t _mutex;
+};
+
+struct SGWaitCondition::PrivateData {
+    PrivateData(void)
+    {
+        int err = pthread_cond_init(&_condition, NULL);
+        assert(err == 0);
+        (void)err;
+    }
+    ~PrivateData(void)
+    {
+        int err = pthread_cond_destroy(&_condition);
+        assert(err == 0);
+        (void)err;
+    }
+
+    void signal(void)
+    {
+        int err = pthread_cond_signal(&_condition);
+        assert(err == 0);
+        (void)err;
+    }
+
+    void broadcast(void)
+    {
+        int err = pthread_cond_broadcast(&_condition);
+        assert(err == 0);
+        (void)err;
+    }
+
+    void wait(SGMutex::PrivateData& mutex)
+    {
+        int err = pthread_cond_wait(&_condition, &mutex._mutex);
+        assert(err == 0);
+        (void)err;
+    }
+
+    bool wait(SGMutex::PrivateData& mutex, unsigned msec)
+    {
+        struct timespec ts;
+#ifdef HAVE_CLOCK_GETTIME
+        if (0 != clock_gettime(CLOCK_REALTIME, &ts))
+            return false;
+#else
+        struct timeval tv;
+        if (0 != gettimeofday(&tv, NULL))
+            return false;
+        ts.tv_sec = tv.tv_sec;
+        ts.tv_nsec = tv.tv_usec * 1000;
 #endif
-#if _MSC_VER >= 1300
-#  include <winsock2.h>
+
+        ts.tv_nsec += 1000000*(msec % 1000);
+        if (1000000000 <= ts.tv_nsec) {
+            ts.tv_nsec -= 1000000000;
+            ts.tv_sec += 1;
+        }
+        ts.tv_sec += msec / 1000;
+
+        int evalue = pthread_cond_timedwait(&_condition, &mutex._mutex, &ts);
+        if (evalue == 0)
+          return true;
+
+        assert(evalue == ETIMEDOUT);
+        return false;
+    }
+
+    pthread_cond_t _condition;
+};
+
 #endif
 
-#include "SGThread.hxx"
-
-void*
-start_handler( void* arg )
-{
-    SGThread* thr = static_cast<SGThread*>(arg);
-    thr->run();
-    return 0;
-}
-
-void
-SGThread::set_cancel( cancel_t mode )
-{
-    switch (mode)
-    {
-    case CANCEL_DISABLE:
-	pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, 0 );
-	break;
-    case CANCEL_DEFERRED:
-	pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, 0 );
-	pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0 );
-	break;
-    case CANCEL_IMMEDIATE:
-	pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, 0 );
-	pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0 );
-	break;
-    default:
-	break;
-    }
+SGThread::SGThread() :
+    _privateData(new PrivateData)
+{
+}
+
+SGThread::~SGThread()
+{
+    delete _privateData;
+    _privateData = 0;
 }
 
 bool
-SGMutex::trylock()
-{
-    int status = pthread_mutex_lock( &mutex );
-    if (status == EBUSY)
-    {
-	return false;
-    }
-    assert( status == 0 );
-    return true;
-}
-
-#if defined(_MSC_VER) || defined(__MINGW32__)
-int gettimeofday(struct timeval* tp, void* tzp) {
-    LARGE_INTEGER t;
-
-    if(QueryPerformanceCounter(&t)) {
-        /* hardware supports a performance counter */
-        LARGE_INTEGER f;
-        QueryPerformanceFrequency(&f);
-        tp->tv_sec = t.QuadPart/f.QuadPart;
-        tp->tv_usec = ((float)t.QuadPart/f.QuadPart*1000*1000)
-            - (tp->tv_sec*1000*1000);
-    } else {
-        /* hardware doesn't support a performance counter, so get the
-           time in a more traditional way. */
-        DWORD t;
-        t = timeGetTime();
-        tp->tv_sec = t / 1000;
-        tp->tv_usec = t % 1000;
-    }
-
-    /* 0 indicates that the call succeeded. */
-    return 0;
-}
-#endif
+SGThread::start()
+{
+    return _privateData->start(*this);
+}
+
+void
+SGThread::join()
+{
+    _privateData->join();
+}
+
+SGMutex::SGMutex() :
+    _privateData(new PrivateData)
+{
+}
+
+SGMutex::~SGMutex()
+{
+    delete _privateData;
+    _privateData = 0;
+}
+
+void
+SGMutex::lock()
+{
+    _privateData->lock();
+}
+
+void
+SGMutex::unlock()
+{
+    _privateData->unlock();
+}
+
+SGWaitCondition::SGWaitCondition() :
+    _privateData(new PrivateData)
+{
+}
+
+SGWaitCondition::~SGWaitCondition()
+{
+    delete _privateData;
+    _privateData = 0;
+}
+
+void
+SGWaitCondition::wait(SGMutex& mutex)
+{
+    _privateData->wait(*mutex._privateData);
+}
 
 bool
-SGPthreadCond::wait( SGMutex& mutex, unsigned long ms )
-{
-    struct timeval now;
-    ::gettimeofday( &now, 0 );
-
-    // Wait time is now + ms milliseconds
-    unsigned int sec = ms / 1000;
-    unsigned int nsec = (ms % 1000) * 1000;
-    struct timespec abstime;
-    abstime.tv_sec = now.tv_sec + sec;
-    abstime.tv_nsec = now.tv_usec*1000 + nsec;
-
-    int status = pthread_cond_timedwait( &cond, &mutex.mutex, &abstime );
-    if (status == ETIMEDOUT)
-    {
-	return false;
-    }
-
-    assert( status == 0 );
-    return true;
-}
-
+SGWaitCondition::wait(SGMutex& mutex, unsigned msec)
+{
+    return _privateData->wait(*mutex._privateData, msec);
+}
+
+void
+SGWaitCondition::signal()
+{
+    _privateData->signal();
+}
+
+void
+SGWaitCondition::broadcast()
+{
+    _privateData->broadcast();
+}

Modified: simgear/trunk/simgear/threads/SGThread.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/threads/SGThread.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/threads/SGThread.hxx (original)
+++ simgear/trunk/simgear/threads/SGThread.hxx Sun Jul 15 09:07:01 2012
@@ -3,6 +3,7 @@
 // Written by Bernie Bright, started April 2001.
 //
 // Copyright (C) 2001  Bernard Bright - bbright at bigpond.net.au
+// Copyright (C) 2011  Mathias Froehlich
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
@@ -18,41 +19,18 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
-// $Id$
 
 #ifndef SGTHREAD_HXX_INCLUDED
 #define SGTHREAD_HXX_INCLUDED 1
 
 #include <simgear/compiler.h>
 
-#include <pthread.h>
-#include <cassert>
-#include <cerrno>
-
-class SGThread;
-
-extern "C" {
-    void* start_handler( void* );
-};
-
 /**
  * Encapsulate generic threading methods.
  * Users derive a class from SGThread and implement the run() member function.
  */
-class SGThread
-{
+class SGThread {
 public:
-    /**
-     * SGThread cancelation modes.
-     */
-    enum cancel_t
-    {
-	CANCEL_DISABLE = 0,
-	CANCEL_DEFERRED,
-	CANCEL_IMMEDIATE
-    };
-public:
-
     /**
      * Create a new thread object.
      * When a SGThread object is created it does not begin execution
@@ -62,18 +40,9 @@
 
     /**
      * Start the underlying thread of execution.
-     * @param cpu An optional parameter to specify on which CPU to run this
-     * thread (only supported on IRIX at this time).
      * @return Pthread error code if execution fails, otherwise returns 0.
      */
-    int start( unsigned cpu = 0 );
-
-    /**
-     * Sends a cancellation request to the underlying thread.  The target
-     * thread will either ignore the request, honor it immediately or defer
-     * it until it reaches a cancellation point.
-     */
-    void cancel();
+    bool start();
 
     /**
      * Suspends the exection of the calling thread until this thread
@@ -90,81 +59,30 @@
     virtual ~SGThread();
 
     /**
-     * Set the threads cancellation mode.
-     * @param mode The required cancellation mode.
-     */
-    void set_cancel( cancel_t mode );
-
-    /**
      * All threads execute by deriving the run() method of SGThread.
      * If this function terminates then the thread also terminates.
      */
     virtual void run() = 0;
 
 private:
+    // Disable copying.
+    SGThread(const SGThread&);
+    SGThread& operator=(const SGThread&);
 
-    /**
-     * Pthread thread identifier.
-     */
-    pthread_t tid;
+    struct PrivateData;
+    PrivateData* _privateData;
 
-    friend void* start_handler( void* );
-
-private:
-    // Disable copying.
-    SGThread( const SGThread& );
-    SGThread& operator=( const SGThread& );
+    friend struct PrivateData;
 };
 
-inline
-SGThread::SGThread()
-{
-}
-
-inline
-SGThread::~SGThread()
-{
-}
-
-inline int
-SGThread::start( unsigned cpu )
-{
-    int status = pthread_create( &tid, 0, start_handler, this );
-    assert( status == 0 );
-    (void)status;
-#if defined( sgi )
-    if ( !status && !cpu )
-        pthread_setrunon_np( cpu );
-#endif
-    return status;
-}
-
-inline void
-SGThread::join()
-{
-    int status = pthread_join( tid, 0 );
-    assert( status == 0 );
-    (void)status;
-}
-
-inline void
-SGThread::cancel()
-{
-    int status = pthread_cancel( tid );
-    assert( status == 0 );
-    (void)status;
-}
+class SGWaitCondition;
 
 /**
  * A mutex is used to protect a section of code such that at any time
  * only a single thread can execute the code.
  */
-class SGMutex
-{
-    friend class SGPthreadCond;
-
+class SGMutex {
 public:
-
     /**
      * Create a new mutex.
      * Under Linux this is a 'fast' mutex.
@@ -186,18 +104,8 @@
      * mutex is already locked and owned by the calling thread, the calling
      * thread is suspended until the mutex is unlocked, effectively causing
      * the calling thread to deadlock.
-     *
-     * @see SGMutex::trylock
      */
     void lock();
-
-    /**
-     * Try to lock the mutex for the current thread.  Behaves like lock except
-     * that it doesn't block the calling thread.
-     * @return true if mutex was successfully locked, otherwise false.
-     * @see SGMutex::lock
-     */
-    bool trylock();
 
     /**
      * Unlock this mutex.
@@ -205,67 +113,37 @@
      */
     void unlock();
 
-protected:
+private:
+    struct PrivateData;
+    PrivateData* _privateData;
 
-    /**
-     * Pthread mutex.
-     */
-    pthread_mutex_t mutex;
+    friend class SGWaitCondition;
 };
 
-inline SGMutex::SGMutex()
-{
-    int status = pthread_mutex_init( &mutex, 0 );
-    assert( status == 0 );
-    (void)status;
-}
-
-inline SGMutex::~SGMutex()
-{
-    int status = pthread_mutex_destroy( &mutex );
-    assert( status == 0 );
-    (void)status;
-}
-
-inline void SGMutex::lock()
-{
-    int status = pthread_mutex_lock( &mutex );
-    assert( status == 0 );
-    (void)status;
-}
-
-inline void SGMutex::unlock()
-{
-    int status = pthread_mutex_unlock( &mutex );
-    assert( status == 0 );
-    (void)status;
-}
-
 /**
- * A condition variable is a synchronization device that allows threads to 
+ * A condition variable is a synchronization device that allows threads to
  * suspend execution until some predicate on shared data is satisfied.
  * A condition variable is always associated with a mutex to avoid race
- * conditions. 
+ * conditions.
  */
-class SGPthreadCond
-{
+class SGWaitCondition {
 public:
     /**
      * Create a new condition variable.
      */
-    SGPthreadCond();
+    SGWaitCondition();
 
     /**
      * Destroy the condition object.
      */
-    ~SGPthreadCond();
+    ~SGWaitCondition();
 
     /**
      * Wait for this condition variable to be signaled.
      *
      * @param SGMutex& reference to a locked mutex.
      */
-    void wait( SGMutex& );
+    void wait(SGMutex&);
 
     /**
      * Wait for this condition variable to be signaled for at most
@@ -274,9 +152,9 @@
      * @param mutex reference to a locked mutex.
      * @param ms milliseconds to wait for a signal.
      *
-     * @return 
+     * @return
      */
-    bool wait( SGMutex& mutex, unsigned long ms );
+    bool wait(SGMutex& mutex, unsigned msec);
 
     /**
      * Wake one thread waiting on this condition variable.
@@ -294,50 +172,11 @@
 
 private:
     // Disable copying.
-    SGPthreadCond(const SGPthreadCond& );
-    SGPthreadCond& operator=(const SGPthreadCond& );
+    SGWaitCondition(const SGWaitCondition&);
+    SGWaitCondition& operator=(const SGWaitCondition&);
 
-private:
-
-    /**
-     * The Pthread conditon variable.
-     */
-    pthread_cond_t cond;
+    struct PrivateData;
+    PrivateData* _privateData;
 };
 
-inline SGPthreadCond::SGPthreadCond()
-{
-    int status = pthread_cond_init( &cond, 0 );
-    assert( status == 0 );
-    (void)status;
-}
-
-inline SGPthreadCond::~SGPthreadCond()
-{
-    int status = pthread_cond_destroy( &cond );
-    assert( status == 0 );
-    (void)status;
-}
-
-inline void SGPthreadCond::signal()
-{
-    int status = pthread_cond_signal( &cond );
-    assert( status == 0 );
-    (void)status;
-}
-
-inline void SGPthreadCond::broadcast()
-{
-    int status = pthread_cond_broadcast( &cond );
-    assert( status == 0 );
-    (void)status;
-}
-
-inline void SGPthreadCond::wait( SGMutex& mutex )
-{
-    int status = pthread_cond_wait( &cond, &mutex.mutex );
-    assert( status == 0 );
-    (void)status;
-}
-
 #endif /* SGTHREAD_HXX_INCLUDED */

Modified: simgear/trunk/simgear/timing/timestamp.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/timing/timestamp.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/timing/timestamp.cxx (original)
+++ simgear/trunk/simgear/timing/timestamp.cxx Sun Jul 15 09:07:01 2012
@@ -31,6 +31,7 @@
 #include <simgear/compiler.h>
 
 #include <ctime>
+#include <cerrno>
 
 #ifdef HAVE_SYS_TIMEB_H
 #  include <sys/timeb.h> // for ftime() and struct timeb
@@ -44,7 +45,6 @@
 
 #if defined(_POSIX_TIMERS) && (0 < _POSIX_TIMERS)
 #  include <time.h>
-#  include <errno.h>
 #endif
 
 #ifdef WIN32
@@ -58,6 +58,29 @@
 
 #include "timestamp.hxx"
 
+#if defined(_POSIX_TIMERS) && (0 < _POSIX_TIMERS)
+static clockid_t getClockId()
+{
+#if defined(_POSIX_MONOTONIC_CLOCK)
+    static clockid_t clockid = CLOCK_MONOTONIC;
+    static bool firstTime = true;
+    if (!firstTime)
+        return clockid;
+
+    firstTime = false;
+    // For the first time test if the monotonic clock is available.
+    // If so use this, if not use the realtime clock.
+    struct timespec ts;
+    if (-1 == clock_gettime(clockid, &ts) && errno == EINVAL)
+        clockid = CLOCK_REALTIME;
+    return clockid;
+#else
+    return CLOCK_REALTIME;
+#endif
+}
+
+#endif
+
 void SGTimeStamp::stamp() {
 #ifdef _WIN32
     unsigned int t;
@@ -66,27 +89,12 @@
     _nsec = ( t - ( _sec * 1000 ) ) * 1000 * 1000;
 #elif defined(_POSIX_TIMERS) && (0 < _POSIX_TIMERS)
     struct timespec ts;
-#if defined(_POSIX_MONOTONIC_CLOCK)
-    static clockid_t clockid = CLOCK_MONOTONIC;
-    static bool firstTime = true;
-    if (firstTime) {
-        firstTime = false;
-        // For the first time test if the monotonic clock is available.
-        // If so use this if not use the realtime clock.
-        if (-1 == clock_gettime(clockid, &ts) && errno == EINVAL)
-            clockid = CLOCK_REALTIME;
-    }
-    clock_gettime(clockid, &ts);
-#else
-    clock_gettime(CLOCK_REALTIME, &ts);
-#endif
+    clock_gettime(getClockId(), &ts);
     _sec = ts.tv_sec;
     _nsec = ts.tv_nsec;
 #elif defined( HAVE_GETTIMEOFDAY )
     struct timeval current;
-    struct timezone tz;
-    // sg_timestamp currtime;
-    gettimeofday(&current, &tz);
+    gettimeofday(&current, NULL);
     _sec = current.tv_sec;
     _nsec = current.tv_usec * 1000;
 #elif defined( HAVE_GETLOCALTIME )
@@ -104,3 +112,185 @@
 #endif
 }
 
+// sleep based timing loop.
+//
+// Calling sleep, even usleep() on linux is less accurate than
+// we like, but it does free up the cpu for other tasks during
+// the sleep so it is desirable.  Because of the way sleep()
+// is implemented in consumer operating systems like windows
+// and linux, you almost always sleep a little longer than the
+// requested amount.
+//
+// To combat the problem of sleeping too long, we calculate the
+// desired wait time and shorten it by 2000us (2ms) to avoid
+// [hopefully] over-sleep'ing.  The 2ms value was arrived at
+// via experimentation.  We follow this up at the end with a
+// simple busy-wait loop to get the final pause timing exactly
+// right.
+//
+// Assuming we don't oversleep by more than 2000us, this
+// should be a reasonable compromise between sleep based
+// waiting, and busy waiting.
+//
+// Usually posix timer resolutions are low enough that we
+// could just leave this to the operating system today.
+// The day where the busy loop was introduced in flightgear,
+// the usual kernels still had just about 10ms (=HZ for
+// the timer tick) accuracy which is too bad to catch 60Hz...
+bool SGTimeStamp::sleepUntil(const SGTimeStamp& abstime)
+{
+#if defined(_POSIX_TIMERS) && (0 < _POSIX_TIMERS)
+    SGTimeStamp abstimeForSleep = abstime;
+
+    // Always undersleep by resolution of the clock
+    struct timespec ts;
+    if (-1 != clock_getres(getClockId(), &ts)) {
+        abstimeForSleep -= SGTimeStamp::fromSecNSec(ts.tv_sec, ts.tv_nsec);
+    } else {
+        abstimeForSleep -= SGTimeStamp::fromSecMSec(0, 2);
+    }
+
+    ts.tv_sec = abstimeForSleep._sec;
+    ts.tv_nsec = abstimeForSleep._nsec;
+    for (;;) {
+        int ret = clock_nanosleep(getClockId(), TIMER_ABSTIME, &ts, NULL);
+        if (-1 == ret && errno != EINTR)
+            return false;
+        if (ret == 0)
+            break;
+    }
+
+    // The busy loop for the rest
+    SGTimeStamp currentTime;
+    do {
+        currentTime.stamp();
+    } while (currentTime < abstime);
+
+    return true;
+
+#elif defined _WIN32
+
+    SGTimeStamp currentTime;
+    currentTime.stamp();
+    if (abstime <= currentTime)
+        return true;
+
+    SGTimeStamp abstimeForSleep = abstime - SGTimeStamp::fromSecMSec(0, 2);
+    for (;abstimeForSleep < currentTime;) {
+        SGTimeStamp timeDiff = abstimeForSleep - currentTime;
+        if (timeDiff < SGTimeStamp::fromSecMSec(0, 1))
+            break;
+        // Don't know, but may be win32 has something better today??
+        Sleep(static_cast<DWORD>(timeDiff.toMSecs()));
+
+        currentTime.stamp();
+    }
+
+    // Follow by a busy loop
+    while (currentTime < abstime) {
+        currentTime.stamp();
+    }
+
+    return true;
+
+#else
+
+    SGTimeStamp currentTime;
+    currentTime.stamp();
+    if (abstime <= currentTime)
+        return true;
+
+    SGTimeStamp abstimeForSleep = abstime - SGTimeStamp::fromSecMSec(0, 2);
+    for (;abstimeForSleep < currentTime;) {
+        SGTimeStamp timeDiff = abstimeForSleep - currentTime;
+        if (timeDiff < SGTimeStamp::fromSecUSec(0, 1))
+            break;
+        // Its documented that some systems bail out on usleep for longer than 1s
+        // since we recheck the current time anyway just wait for
+        // less than a second multiple times
+        bool truncated = false;
+        if (SGTimeStamp::fromSec(1) < timeDiff) {
+            timeDiff = SGTimeStamp::fromSec(1);
+            truncated = true;
+        }
+        int ret = usleep(static_cast<int>(timeDiff.toUSecs()));
+        if (-1 == ret && errno != EINTR)
+            return false;
+        if (ret == 0 && !truncated)
+            break;
+
+        currentTime.stamp();
+    }
+
+    // Follow by a busy loop
+    while (currentTime < abstime) {
+        currentTime.stamp();
+    }
+
+    return true;
+
+#endif
+}
+
+bool SGTimeStamp::sleepFor(const SGTimeStamp& reltime)
+{
+#if defined(_POSIX_TIMERS) && (0 < _POSIX_TIMERS)
+    struct timespec ts;
+    ts.tv_sec = reltime._sec;
+    ts.tv_nsec = reltime._nsec;
+    for (;;) {
+        struct timespec rem;
+        int ret = clock_nanosleep(getClockId(), 0, &ts, &rem);
+        if (-1 == ret && errno != EINTR)
+            return false;
+        if (ret == 0)
+            break;
+        // Use the remainder for the next cycle.
+        ts = rem;
+    }
+    return true;
+#elif defined _WIN32
+    if (reltime < SGTimeStamp::fromSecMSec(0, 1))
+        return true;
+    // Don't know, but may be win32 has something better today??
+    Sleep(static_cast<DWORD>(reltime.toMSecs()));
+    return true;
+#else
+    SGTimeStamp abstime;
+    abstime.stamp();
+    abstime += reltime;
+
+    SGTimeStamp currentTime;
+    currentTime.stamp();
+    for (;abstime < currentTime;) {
+        SGTimeStamp timeDiff = abstime - currentTime;
+        if (timeDiff < SGTimeStamp::fromSecUSec(0, 1))
+            break;
+        // Its documented that some systems bail out on usleep for longer than 1s
+        // since we recheck the current time anyway just wait for
+        // less than a second multiple times
+        bool truncated = false;
+        if (SGTimeStamp::fromSec(1) < timeDiff) {
+            timeDiff = SGTimeStamp::fromSec(1);
+            truncated = true;
+        }
+        int ret = usleep(static_cast<int>(timeDiff.toUSecs()));
+        if (-1 == ret && errno != EINTR)
+            return false;
+        if (ret == 0 && !truncated)
+            break;
+
+        currentTime.stamp();
+    }
+
+    return true;
+#endif
+}
+
+int SGTimeStamp::elapsedMSec() const
+{
+    SGTimeStamp now;
+    now.stamp();
+    
+    return static_cast<int>((now - *this).toMSecs());
+}

Modified: simgear/trunk/simgear/timing/timestamp.hxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/timing/timestamp.hxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/timing/timestamp.hxx (original)
+++ simgear/trunk/simgear/timing/timestamp.hxx Sun Jul 15 09:07:01 2012
@@ -184,6 +184,8 @@
     { SGTimeStamp ts; ts.setTime(sec); return ts; }
     static SGTimeStamp fromSec(const double& sec)
     { SGTimeStamp ts; ts.setTime(sec); return ts; }
+    static SGTimeStamp fromMSec(nsec_type msec)
+    { return SGTimeStamp(0, 1000*1000*msec); }
     static SGTimeStamp fromUSec(nsec_type usec)
     { return SGTimeStamp(0, 1000*usec); }
     static SGTimeStamp fromNSec(nsec_type nsec)
@@ -195,6 +197,26 @@
     static SGTimeStamp now()
     { SGTimeStamp ts; ts.stamp(); return ts; }
 
+    /**
+     *  Sleep until the time of abstime is passed.
+     */
+    static bool sleepUntil(const SGTimeStamp& abstime);
+
+    /**
+     *  Sleep for reltime.
+     */
+    static bool sleepFor(const SGTimeStamp& reltime);
+
+    /**
+     *  Alias for the most common use case with milliseconds.
+     */
+    static bool sleepForMSec(unsigned msec)
+    { return sleepFor(fromMSec(msec)); }
+
+    /**
+     * elapsed time since the stamp was taken, in msec
+     */
+    int elapsedMSec() const;
 private:
     SGTimeStamp(sec_type sec, nsec_type nsec)
     { setTime(sec, nsec); }

Modified: simgear/trunk/simgear/timing/timezone.cxx
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/simgear/timing/timezone.cxx?rev=196&op=diff
==============================================================================
--- simgear/trunk/simgear/timing/timezone.cxx (original)
+++ simgear/trunk/simgear/timing/timezone.cxx Sun Jul 15 09:07:01 2012
@@ -25,6 +25,10 @@
  * used in order to get the local time. 
  *
  ************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
 
 #include <errno.h>
 #include <string.h>
@@ -139,7 +143,8 @@
     errno = 0;
 
     while (1) {
-        fgets(buffer, 256, infile);
+        if (0 == fgets(buffer, 256, infile))
+            break;
         if (feof(infile)) {
             break;
         }

Modified: simgear/trunk/version
URL: http://svn.debian.org/wsvn/pkg-fgfs/simgear/trunk/version?rev=196&op=diff
==============================================================================
--- simgear/trunk/version (original)
+++ simgear/trunk/version Sun Jul 15 09:07:01 2012
@@ -1,1 +1,1 @@
-2.4.0
+2.6.0




More information about the pkg-fgfs-crew mailing list