From b159a72ce97db3c1903dd346307eecd5f18e5ffe Mon Sep 17 00:00:00 2001 From: Martin Spott Date: Mon, 5 Sep 2011 18:45:33 +0200 Subject: [PATCH 01/32] Fix CMake HLA fix --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49916a08..8a2a6f94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,7 +89,7 @@ check_include_file(windows.h HAVE_WINDOWS_H) if(ENABLE_RTI) # See if we have any rti library variant installed -find_package(RTI) + find_package(RTI) endif(ENABLE_RTI) check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) From 20bd0737a22eb9825fb790c9a2ac7bc2eb6ba9ae Mon Sep 17 00:00:00 2001 From: Stuart Buchanan Date: Thu, 15 Sep 2011 21:11:00 +0100 Subject: [PATCH 02/32] Make tree textures consistent across runs by replacing rand() call with something deterministic. --- simgear/scene/tgdb/TreeBin.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/scene/tgdb/TreeBin.cxx b/simgear/scene/tgdb/TreeBin.cxx index 56c5d415..17da8374 100644 --- a/simgear/scene/tgdb/TreeBin.cxx +++ b/simgear/scene/tgdb/TreeBin.cxx @@ -253,7 +253,7 @@ struct AddTreesLeafObject { void operator() (LOD* lod, const TreeBin::Tree& tree) const { - Geode* geode = static_cast(lod->getChild(rand() % SG_TREE_FADE_OUT_LEVELS)); + Geode* geode = static_cast(lod->getChild(int(tree.position.x() * 10.0f) % lod->getNumChildren())); addTreeToLeafGeode(geode, tree.position); } }; From bcb320b537b6f7e5e3724e8a30d309322171eb43 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Mon, 3 Oct 2011 11:21:27 +0200 Subject: [PATCH 03/32] hla: Provide a directly property based api for property data element. --- simgear/hla/HLAPropertyDataElement.cxx | 108 +++++++++++++++++-------- simgear/hla/HLAPropertyDataElement.hxx | 74 ++--------------- 2 files changed, 81 insertions(+), 101 deletions(-) diff --git a/simgear/hla/HLAPropertyDataElement.cxx b/simgear/hla/HLAPropertyDataElement.cxx index db4f00ba..9b05da43 100644 --- a/simgear/hla/HLAPropertyDataElement.cxx +++ b/simgear/hla/HLAPropertyDataElement.cxx @@ -23,70 +23,70 @@ namespace simgear { class HLAPropertyDataElement::DecodeVisitor : public HLADataTypeDecodeVisitor { public: - DecodeVisitor(HLADecodeStream& stream, HLAPropertyReference& propertyReference) : + DecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) : HLADataTypeDecodeVisitor(stream), - _propertyReference(propertyReference) + _propertyNode(propertyNode) { } 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); } virtual void apply(const HLAFixedArrayDataType& dataType) @@ -99,7 +99,7 @@ public: dataType.getElementDataType()->accept(visitor); value.push_back(visitor.getValue()); } - _propertyReference.setStringValue(value); + _propertyNode.setStringValue(value); } virtual void apply(const HLAVariableArrayDataType& dataType) { @@ -113,65 +113,65 @@ public: dataType.getElementDataType()->accept(visitor); value.push_back(visitor.getValue()); } - _propertyReference.setStringValue(value); + _propertyNode.setStringValue(value); } protected: - HLAPropertyReference& _propertyReference; + SGPropertyNode& _propertyNode; }; class HLAPropertyDataElement::EncodeVisitor : public HLADataTypeEncodeVisitor { public: - EncodeVisitor(HLAEncodeStream& stream, const HLAPropertyReference& propertyReference) : + EncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) : HLADataTypeEncodeVisitor(stream), - _propertyReference(propertyReference) + _propertyNode(propertyNode) { } virtual void apply(const HLAInt8DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + dataType.encode(_stream, _propertyNode.getIntValue()); } virtual void apply(const HLAUInt8DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + dataType.encode(_stream, _propertyNode.getIntValue()); } virtual void apply(const HLAInt16DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + dataType.encode(_stream, _propertyNode.getIntValue()); } virtual void apply(const HLAUInt16DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + dataType.encode(_stream, _propertyNode.getIntValue()); } virtual void apply(const HLAInt32DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + dataType.encode(_stream, _propertyNode.getIntValue()); } virtual void apply(const HLAUInt32DataType& dataType) { - dataType.encode(_stream, _propertyReference.getIntValue()); + dataType.encode(_stream, _propertyNode.getIntValue()); } virtual void apply(const HLAInt64DataType& dataType) { - dataType.encode(_stream, _propertyReference.getLongValue()); + dataType.encode(_stream, _propertyNode.getLongValue()); } virtual void apply(const HLAUInt64DataType& dataType) { - dataType.encode(_stream, _propertyReference.getLongValue()); + dataType.encode(_stream, _propertyNode.getLongValue()); } virtual void apply(const HLAFloat32DataType& dataType) { - dataType.encode(_stream, _propertyReference.getFloatValue()); + dataType.encode(_stream, _propertyNode.getFloatValue()); } virtual void apply(const HLAFloat64DataType& dataType) { - dataType.encode(_stream, _propertyReference.getDoubleValue()); + dataType.encode(_stream, _propertyNode.getDoubleValue()); } virtual void apply(const HLAFixedArrayDataType& dataType) { unsigned numElements = dataType.getNumElements(); - std::string value = _propertyReference.getStringValue(); + std::string value = _propertyNode.getStringValue(); for (unsigned i = 0; i < numElements; ++i) { if (i < value.size()) { HLATemplateEncodeVisitor visitor(_stream, value[i]); @@ -185,7 +185,7 @@ public: virtual void apply(const HLAVariableArrayDataType& dataType) { - std::string value = _propertyReference.getStringValue(); + std::string value = _propertyNode.getStringValue(); HLATemplateEncodeVisitor numElementsVisitor(_stream, value.size()); dataType.getSizeDataType()->accept(numElementsVisitor); for (unsigned i = 0; i < value.size(); ++i) { @@ -195,7 +195,7 @@ public: } protected: - const HLAPropertyReference& _propertyReference; + const SGPropertyNode& _propertyNode; }; HLAPropertyDataElement::HLAPropertyDataElement(HLAPropertyReference* propertyReference) : @@ -203,12 +203,27 @@ HLAPropertyDataElement::HLAPropertyDataElement(HLAPropertyReference* propertyRef { } -HLAPropertyDataElement::HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference) : +HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, HLAPropertyReference* propertyReference) : _dataType(dataType), _propertyReference(propertyReference) { } +HLAPropertyDataElement::HLAPropertyDataElement() +{ +} + +HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode) +{ + setPropertyNode(propertyNode); +} + +HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) : + _dataType(dataType) +{ + setPropertyNode(propertyNode); +} + HLAPropertyDataElement::~HLAPropertyDataElement() { } @@ -218,8 +233,8 @@ HLAPropertyDataElement::encode(HLAEncodeStream& stream) const { if (!_dataType.valid()) return false; - if (_propertyReference.valid()) { - EncodeVisitor visitor(stream, *_propertyReference); + if (const SGPropertyNode* propertyNode = getPropertyNode()) { + EncodeVisitor visitor(stream, *propertyNode); _dataType->accept(visitor); } else { HLADataTypeEncodeVisitor visitor(stream); @@ -233,8 +248,8 @@ HLAPropertyDataElement::decode(HLADecodeStream& stream) { if (!_dataType.valid()) return false; - if (_propertyReference.valid()) { - DecodeVisitor visitor(stream, *_propertyReference); + if (SGPropertyNode* propertyNode = getPropertyNode()) { + DecodeVisitor visitor(stream, *propertyNode); _dataType->accept(visitor); } else { HLADataTypeDecodeVisitor visitor(stream); @@ -266,4 +281,27 @@ HLAPropertyDataElement::setDataType(const HLADataType* dataType) return false; } +void +HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode) +{ + _propertyReference = new HLAPropertyReference; + _propertyReference->setRootNode(propertyNode); +} + +SGPropertyNode* +HLAPropertyDataElement::getPropertyNode() +{ + if (!_propertyReference.valid()) + return 0; + return _propertyReference->getPropertyNode(); +} + +const SGPropertyNode* +HLAPropertyDataElement::getPropertyNode() const +{ + if (!_propertyReference.valid()) + return 0; + return _propertyReference->getPropertyNode(); +} + } // namespace simgear diff --git a/simgear/hla/HLAPropertyDataElement.hxx b/simgear/hla/HLAPropertyDataElement.hxx index 32dba058..51d1729b 100644 --- a/simgear/hla/HLAPropertyDataElement.hxx +++ b/simgear/hla/HLAPropertyDataElement.hxx @@ -32,71 +32,6 @@ public: _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(); } @@ -150,7 +85,10 @@ private: class HLAPropertyDataElement : public HLADataElement { public: HLAPropertyDataElement(HLAPropertyReference* propertyReference); - HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference); + HLAPropertyDataElement(const HLADataType* dataType, HLAPropertyReference* propertyReference); + HLAPropertyDataElement(); + HLAPropertyDataElement(SGPropertyNode* propertyNode); + HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode); virtual ~HLAPropertyDataElement(); virtual bool encode(HLAEncodeStream& stream) const; @@ -159,6 +97,10 @@ public: 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; From 2e13c1fa4bc13f2956ccc719d2ea223713fb1e85 Mon Sep 17 00:00:00 2001 From: ThorstenB Date: Mon, 3 Oct 2011 11:57:48 +0200 Subject: [PATCH 04/32] Add convenience class for change listener callbacks. --- simgear/props/props.hxx | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/simgear/props/props.hxx b/simgear/props/props.hxx index 8cf38e6d..38c9c0a2 100644 --- a/simgear/props/props.hxx +++ b/simgear/props/props.hxx @@ -1938,6 +1938,36 @@ struct Hash }; } } + +/** Convenience class for change listener callbacks without + * creating a derived class implementing a "valueChanged" method. + * Also removes listener on destruction automatically. + */ +template +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 From 92976b7735635e60843a688a86e75a5707f35b98 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Mon, 3 Oct 2011 13:11:27 +0200 Subject: [PATCH 05/32] hla: remove the now unused HLAPropertyReference{,Set}. --- simgear/hla/HLAPropertyDataElement.cxx | 27 ++++------- simgear/hla/HLAPropertyDataElement.hxx | 64 +------------------------- 2 files changed, 10 insertions(+), 81 deletions(-) diff --git a/simgear/hla/HLAPropertyDataElement.cxx b/simgear/hla/HLAPropertyDataElement.cxx index 9b05da43..121eddda 100644 --- a/simgear/hla/HLAPropertyDataElement.cxx +++ b/simgear/hla/HLAPropertyDataElement.cxx @@ -198,17 +198,6 @@ protected: const SGPropertyNode& _propertyNode; }; -HLAPropertyDataElement::HLAPropertyDataElement(HLAPropertyReference* propertyReference) : - _propertyReference(propertyReference) -{ -} - -HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, HLAPropertyReference* propertyReference) : - _dataType(dataType), - _propertyReference(propertyReference) -{ -} - HLAPropertyDataElement::HLAPropertyDataElement() { } @@ -224,6 +213,11 @@ HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPr setPropertyNode(propertyNode); } +HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) : + _dataType(dataType) +{ +} + HLAPropertyDataElement::~HLAPropertyDataElement() { } @@ -284,24 +278,19 @@ HLAPropertyDataElement::setDataType(const HLADataType* dataType) void HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode) { - _propertyReference = new HLAPropertyReference; - _propertyReference->setRootNode(propertyNode); + _propertyNode = propertyNode; } SGPropertyNode* HLAPropertyDataElement::getPropertyNode() { - if (!_propertyReference.valid()) - return 0; - return _propertyReference->getPropertyNode(); + return _propertyNode.get(); } const SGPropertyNode* HLAPropertyDataElement::getPropertyNode() const { - if (!_propertyReference.valid()) - return 0; - return _propertyReference->getPropertyNode(); + return _propertyNode.get(); } } // namespace simgear diff --git a/simgear/hla/HLAPropertyDataElement.hxx b/simgear/hla/HLAPropertyDataElement.hxx index 51d1729b..076d85ba 100644 --- a/simgear/hla/HLAPropertyDataElement.hxx +++ b/simgear/hla/HLAPropertyDataElement.hxx @@ -18,77 +18,17 @@ #ifndef HLAPropertyDataElement_hxx #define HLAPropertyDataElement_hxx -#include #include #include "HLADataElement.hxx" namespace simgear { -class HLAPropertyReference : public SGReferenced { -public: - HLAPropertyReference() - { } - HLAPropertyReference(const std::string& relativePath) : - _relativePath(relativePath) - { } - - SGPropertyNode* getPropertyNode() - { return _propertyNode.get(); } - - void setRootNode(SGPropertyNode* rootNode) - { - if (!rootNode) - _propertyNode.clear(); - else - _propertyNode = rootNode->getNode(_relativePath, true); - } - -private: - std::string _relativePath; - SGSharedPtr _propertyNode; -}; - -class HLAPropertyReferenceSet : public SGReferenced { -public: - void insert(const SGSharedPtr& propertyReference) - { - _propertyReferenceSet.insert(propertyReference); - propertyReference->setRootNode(_rootNode.get()); - } - void remove(const SGSharedPtr& 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 _rootNode; - - typedef std::set > PropertyReferenceSet; - PropertyReferenceSet _propertyReferenceSet; -}; - class HLAPropertyDataElement : public HLADataElement { public: - HLAPropertyDataElement(HLAPropertyReference* propertyReference); - HLAPropertyDataElement(const HLADataType* dataType, HLAPropertyReference* propertyReference); HLAPropertyDataElement(); HLAPropertyDataElement(SGPropertyNode* propertyNode); HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode); + HLAPropertyDataElement(const HLADataType* dataType); virtual ~HLAPropertyDataElement(); virtual bool encode(HLAEncodeStream& stream) const; @@ -106,7 +46,7 @@ private: class EncodeVisitor; SGSharedPtr _dataType; - SGSharedPtr _propertyReference; + SGSharedPtr _propertyNode; }; } // namespace simgear From 5871b54172ea5d6c97f82c71f8df598e63a96c16 Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 4 Oct 2011 15:06:12 +0100 Subject: [PATCH 06/32] Build decode_bin helper under CMake. --- simgear/io/CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index e85d9659..ac2b7781 100644 --- a/simgear/io/CMakeLists.txt +++ b/simgear/io/CMakeLists.txt @@ -57,3 +57,12 @@ target_link_libraries(httpget ${CMAKE_THREAD_LIBS_INIT} ${WINSOCK_LIBRARY} ${RT_LIBRARY}) + +add_executable(decode_binobj decode_binobj.cxx) +target_link_libraries(decode_binobj + sgbucket sgio sgstructure sgthreads sgtiming sgmisc sgdebug + ${CMAKE_THREAD_LIBS_INIT} + ${WINSOCK_LIBRARY} + ${ZLIB_LIBRARY} + ${RT_LIBRARY}) + \ No newline at end of file From 7ffc84fb866d82b14781ff404960b5e93785c966 Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 4 Oct 2011 17:53:53 +0100 Subject: [PATCH 07/32] Fix decode_bin linkage with GNU ld. --- simgear/io/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index ac2b7781..01560b39 100644 --- a/simgear/io/CMakeLists.txt +++ b/simgear/io/CMakeLists.txt @@ -60,7 +60,7 @@ target_link_libraries(httpget add_executable(decode_binobj decode_binobj.cxx) target_link_libraries(decode_binobj - sgbucket sgio sgstructure sgthreads sgtiming sgmisc sgdebug + sgio sgbucket sgstructure sgthreads sgtiming sgmisc sgdebug ${CMAKE_THREAD_LIBS_INIT} ${WINSOCK_LIBRARY} ${ZLIB_LIBRARY} From d951a55be0b032350e04d68d561bb21dfa69ec87 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 4 Oct 2011 19:48:34 +0200 Subject: [PATCH 08/32] hla: detect string and opaque data types. --- simgear/hla/HLAArrayDataType.cxx | 18 ++++++++++++++++-- simgear/hla/HLAArrayDataType.hxx | 12 +++++++++++- simgear/hla/HLAOMTXmlVisitor.cxx | 11 ++++++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/simgear/hla/HLAArrayDataType.cxx b/simgear/hla/HLAArrayDataType.cxx index 0eac2364..f52da283 100644 --- a/simgear/hla/HLAArrayDataType.cxx +++ b/simgear/hla/HLAArrayDataType.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -22,7 +22,9 @@ namespace simgear { HLAArrayDataType::HLAArrayDataType(const std::string& name) : - HLADataType(name) + HLADataType(name), + _isOpaque(false), + _isString(false) { } @@ -51,6 +53,18 @@ HLAArrayDataType::setElementDataType(const HLADataType* elementDataType) _elementDataType = elementDataType; } +void +HLAArrayDataType::setIsOpaque(bool isOpaque) +{ + _isOpaque = isOpaque; +} + +void +HLAArrayDataType::setIsString(bool isString) +{ + _isString = isString; +} + /////////////////////////////////////////////////////////////////////////////////// HLAFixedArrayDataType::HLAFixedArrayDataType(const std::string& name) : diff --git a/simgear/hla/HLAArrayDataType.hxx b/simgear/hla/HLAArrayDataType.hxx index eac645b4..a38f05bc 100644 --- a/simgear/hla/HLAArrayDataType.hxx +++ b/simgear/hla/HLAArrayDataType.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -42,8 +42,18 @@ public: 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 _elementDataType; + bool _isOpaque; + bool _isString; }; class HLAFixedArrayDataType : public HLAArrayDataType { diff --git a/simgear/hla/HLAOMTXmlVisitor.cxx b/simgear/hla/HLAOMTXmlVisitor.cxx index 06351d6a..fa731eb3 100644 --- a/simgear/hla/HLAOMTXmlVisitor.cxx +++ b/simgear/hla/HLAOMTXmlVisitor.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -439,6 +439,15 @@ HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName, HLAOMTXmlVis } 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; } From 595328963a34ba8040d16e825f89973d70ad8b3d Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 4 Oct 2011 20:21:12 +0200 Subject: [PATCH 09/32] hla: provide a data type visitor building a default data element tree. --- simgear/hla/CMakeLists.txt | 1 + simgear/hla/HLADataTypeVisitor.hxx | 39 +++++++++++++++++++++++++++++- simgear/hla/HLAObjectInstance.cxx | 28 +++++++++------------ simgear/hla/Makefile.am | 1 + 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/simgear/hla/CMakeLists.txt b/simgear/hla/CMakeLists.txt index 207210ab..a822fc24 100644 --- a/simgear/hla/CMakeLists.txt +++ b/simgear/hla/CMakeLists.txt @@ -32,6 +32,7 @@ set(HLA_SOURCES HLABasicDataType.cxx HLADataElement.cxx HLADataType.cxx + HLADataTypeVisitor.cxx HLAEnumeratedDataElement.cxx HLAEnumeratedDataType.cxx HLAFederate.cxx diff --git a/simgear/hla/HLADataTypeVisitor.hxx b/simgear/hla/HLADataTypeVisitor.hxx index d3cd9b22..2af1012c 100644 --- a/simgear/hla/HLADataTypeVisitor.hxx +++ b/simgear/hla/HLADataTypeVisitor.hxx @@ -24,7 +24,7 @@ #include #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 @@ inline void HLADataTypeEncodeVisitor::apply(const HLAVariableArrayDataType& data 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 _dataElement; +}; + } // namespace simgear #endif diff --git a/simgear/hla/HLAObjectInstance.cxx b/simgear/hla/HLAObjectInstance.cxx index 0324d328..ae726ee4 100644 --- a/simgear/hla/HLAObjectInstance.cxx +++ b/simgear/hla/HLAObjectInstance.cxx @@ -123,7 +123,7 @@ HLAObjectInstance::getAttributeDataElement(unsigned index) const 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 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLASCharDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAUInt8DataType& dataType) { @@ -158,7 +158,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLAUCharDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAInt16DataType& dataType) { @@ -166,7 +166,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLAShortDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAUInt16DataType& dataType) { @@ -174,7 +174,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLAUShortDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAInt32DataType& dataType) { @@ -182,7 +182,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLAIntDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAUInt32DataType& dataType) { @@ -190,7 +190,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLAUIntDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAInt64DataType& dataType) { @@ -198,7 +198,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLALongDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAUInt64DataType& dataType) { @@ -206,7 +206,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLAULongDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAFloat32DataType& dataType) { @@ -214,7 +214,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLAFloatDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAFloat64DataType& dataType) { @@ -222,7 +222,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLADoubleDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory { @@ -287,7 +287,7 @@ public: if (_dataElement.valid()) return; - _dataElement = new HLAEnumeratedDataElement(&dataType); + HLADataElementFactoryVisitor::apply(dataType); } virtual void apply(const HLAFixedRecordDataType& dataType) @@ -357,9 +357,6 @@ public: _dataElement = variantDataElement; } - const SGSharedPtr& getDataElement() const - { return _dataElement; } - private: SGSharedPtr createDataElement(const HLADataElement::Path& path, const HLADataType& dataType) { @@ -381,7 +378,6 @@ private: return dataElement; } - SGSharedPtr _dataElement; const HLAPathElementMap& _pathElementMap; HLADataElement::Path _path; }; diff --git a/simgear/hla/Makefile.am b/simgear/hla/Makefile.am index 67542ddb..e214e6a0 100644 --- a/simgear/hla/Makefile.am +++ b/simgear/hla/Makefile.am @@ -35,6 +35,7 @@ libsghla_a_SOURCES = \ HLABasicDataType.cxx \ HLADataElement.cxx \ HLADataType.cxx \ + HLADataTypeVisitor.cxx \ HLAEnumeratedDataElement.cxx \ HLAEnumeratedDataType.cxx \ HLAFederate.cxx \ From 264e336a4941a719362c75b3415a92e9098b2719 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 4 Oct 2011 20:27:59 +0200 Subject: [PATCH 10/32] hla: add missing file fir the last commit. --- simgear/hla/HLADataTypeVisitor.cxx | 188 +++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 simgear/hla/HLADataTypeVisitor.cxx diff --git a/simgear/hla/HLADataTypeVisitor.cxx b/simgear/hla/HLADataTypeVisitor.cxx new file mode 100644 index 00000000..a13d12a4 --- /dev/null +++ b/simgear/hla/HLADataTypeVisitor.cxx @@ -0,0 +1,188 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLADataTypeVisitor.hxx" + +#include "HLAArrayDataElement.hxx" +#include "HLABasicDataElement.hxx" +#include "HLADataTypeVisitor.hxx" +#include "HLAEnumeratedDataElement.hxx" +#include "HLAFixedRecordDataElement.hxx" +#include "HLAVariantDataElement.hxx" + +namespace simgear { + +HLADataElementFactoryVisitor::~HLADataElementFactoryVisitor() +{ +} + +void +HLADataElementFactoryVisitor::apply(const HLADataType& dataType) +{ + SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \"" + << dataType.getName() << "\""); +} + +void +HLADataElementFactoryVisitor::apply(const HLAInt8DataType& dataType) +{ + _dataElement = new HLASCharDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAUInt8DataType& dataType) +{ + _dataElement = new HLAUCharDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAInt16DataType& dataType) +{ + _dataElement = new HLAShortDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAUInt16DataType& dataType) +{ + _dataElement = new HLAUShortDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAInt32DataType& dataType) +{ + _dataElement = new HLAIntDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAUInt32DataType& dataType) +{ + _dataElement = new HLAUIntDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAInt64DataType& dataType) +{ + _dataElement = new HLALongDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAUInt64DataType& dataType) +{ + _dataElement = new HLAULongDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAFloat32DataType& dataType) +{ + _dataElement = new HLAFloatDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAFloat64DataType& dataType) +{ + _dataElement = new HLADoubleDataElement(&dataType); +} + +class HLADataElementFactoryVisitor::ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory { +public: + virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index) + { + const HLADataType* dataType = element.getElementDataType(); + if (!dataType) + return 0; + + HLADataElementFactoryVisitor visitor; + dataType->accept(visitor); + return visitor.getDataElement(); + } +}; + +void +HLADataElementFactoryVisitor::apply(const HLAFixedArrayDataType& dataType) +{ + if (dataType.getIsString()) { + _dataElement = new HLAStringDataElement(&dataType); + } else { + SGSharedPtr arrayDataElement; + arrayDataElement = new HLAArrayDataElement(&dataType); + arrayDataElement->setDataElementFactory(new ArrayDataElementFactory); + arrayDataElement->setNumElements(dataType.getNumElements()); + _dataElement = arrayDataElement; + } +} + +void +HLADataElementFactoryVisitor::apply(const HLAVariableArrayDataType& dataType) +{ + if (dataType.getIsString()) { + _dataElement = new HLAStringDataElement(&dataType); + } else { + SGSharedPtr arrayDataElement; + arrayDataElement = new HLAArrayDataElement(&dataType); + arrayDataElement->setDataElementFactory(new ArrayDataElementFactory); + _dataElement = arrayDataElement; + } +} + +void +HLADataElementFactoryVisitor::apply(const HLAEnumeratedDataType& dataType) +{ + _dataElement = new HLAEnumeratedDataElement(&dataType); +} + +void +HLADataElementFactoryVisitor::apply(const HLAFixedRecordDataType& dataType) +{ + SGSharedPtr recordDataElement; + recordDataElement = new HLAFixedRecordDataElement(&dataType); + + unsigned numFields = dataType.getNumFields(); + for (unsigned i = 0; i < numFields; ++i) { + HLADataElementFactoryVisitor visitor; + dataType.getFieldDataType(i)->accept(visitor); + recordDataElement->setField(i, visitor._dataElement.get()); + } + + _dataElement = recordDataElement; +} + +class HLADataElementFactoryVisitor::VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory { +public: + 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; + HLADataElementFactoryVisitor visitor; + alternativeDataType->accept(visitor); + return visitor.getDataElement(); + } +}; + +void +HLADataElementFactoryVisitor::apply(const HLAVariantDataType& dataType) +{ + SGSharedPtr variantDataElement; + variantDataElement = new HLAVariantDataElement(&dataType); + variantDataElement->setDataElementFactory(new VariantDataElementFactory); + _dataElement = variantDataElement; +} + +} // namespace simgear From 7a98f89e1be486be5182fc4d6849bd82313e59e6 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 4 Oct 2011 20:32:34 +0200 Subject: [PATCH 11/32] hla: provide a more general property data element implementation. --- simgear/hla/HLAPropertyDataElement.cxx | 446 +++++++++++++++++++++---- simgear/hla/HLAPropertyDataElement.hxx | 15 +- 2 files changed, 402 insertions(+), 59 deletions(-) diff --git a/simgear/hla/HLAPropertyDataElement.cxx b/simgear/hla/HLAPropertyDataElement.cxx index 121eddda..e8a931ee 100644 --- a/simgear/hla/HLAPropertyDataElement.cxx +++ b/simgear/hla/HLAPropertyDataElement.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -17,16 +17,21 @@ #include "HLAPropertyDataElement.hxx" +#include "HLAArrayDataElement.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, SGPropertyNode& propertyNode) : + ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) : HLADataTypeDecodeVisitor(stream), _propertyNode(propertyNode) { } + virtual ~ScalarDecodeVisitor() + { } virtual void apply(const HLAInt8DataType& dataType) { @@ -89,43 +94,18 @@ public: _propertyNode.setDoubleValue(value); } - virtual void apply(const HLAFixedArrayDataType& dataType) - { - unsigned numElements = dataType.getNumElements(); - std::string value; - value.reserve(numElements); - for (unsigned i = 0; i < numElements; ++i) { - HLATemplateDecodeVisitor visitor(_stream); - dataType.getElementDataType()->accept(visitor); - value.push_back(visitor.getValue()); - } - _propertyNode.setStringValue(value); - } - virtual void apply(const HLAVariableArrayDataType& dataType) - { - HLATemplateDecodeVisitor numElementsVisitor(_stream); - dataType.getSizeDataType()->accept(numElementsVisitor); - unsigned numElements = numElementsVisitor.getValue(); - std::string value; - value.reserve(numElements); - for (unsigned i = 0; i < numElements; ++i) { - HLATemplateDecodeVisitor visitor(_stream); - dataType.getElementDataType()->accept(visitor); - value.push_back(visitor.getValue()); - } - _propertyNode.setStringValue(value); - } - protected: SGPropertyNode& _propertyNode; }; -class HLAPropertyDataElement::EncodeVisitor : public HLADataTypeEncodeVisitor { +class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor { public: - EncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) : + ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) : HLADataTypeEncodeVisitor(stream), _propertyNode(propertyNode) { } + virtual ~ScalarEncodeVisitor() + { } virtual void apply(const HLAInt8DataType& dataType) { @@ -168,6 +148,116 @@ public: dataType.encode(_stream, _propertyNode.getDoubleValue()); } +protected: + const SGPropertyNode& _propertyNode; +}; + +class HLAPropertyDataElement::ScalarDataElement : public HLADataElement { +public: + ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode); + virtual ~ScalarDataElement(); + + virtual bool encode(HLAEncodeStream& stream) const; + virtual bool decode(HLADecodeStream& stream); + + virtual const HLADataType* getDataType() const; + virtual bool setDataType(const HLADataType* dataType); + +private: + SGSharedPtr _dataType; + SGSharedPtr _propertyNode; +}; + +HLAPropertyDataElement::ScalarDataElement::ScalarDataElement(const HLABasicDataType* dataType, SGPropertyNode* propertyNode) : + _dataType(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; +} + +const HLADataType* +HLAPropertyDataElement::ScalarDataElement::getDataType() const +{ + return _dataType.get(); +} + +bool +HLAPropertyDataElement::ScalarDataElement::setDataType(const HLADataType* dataType) +{ + if (!dataType) + return false; + const HLABasicDataType* basicDataType = dataType->toBasicDataType(); + if (!basicDataType) + return false; + _dataType = basicDataType; + return true; +} + + +class HLAPropertyDataElement::StringDecodeVisitor : public HLADataTypeDecodeVisitor { +public: + StringDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) : + HLADataTypeDecodeVisitor(stream), + _propertyNode(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 visitor(_stream); + dataType.getElementDataType()->accept(visitor); + value.push_back(visitor.getValue()); + } + _propertyNode.setStringValue(value); + } + virtual void apply(const HLAVariableArrayDataType& dataType) + { + HLATemplateDecodeVisitor numElementsVisitor(_stream); + dataType.getSizeDataType()->accept(numElementsVisitor); + std::string::size_type numElements = numElementsVisitor.getValue(); + std::string value; + value.reserve(numElements); + for (std::string::size_type i = 0; i < numElements; ++i) { + HLATemplateDecodeVisitor visitor(_stream); + dataType.getElementDataType()->accept(visitor); + value.push_back(visitor.getValue()); + } + _propertyNode.setStringValue(value); + } + +protected: + SGPropertyNode& _propertyNode; +}; + +class HLAPropertyDataElement::StringEncodeVisitor : public HLADataTypeEncodeVisitor { +public: + StringEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) : + HLADataTypeEncodeVisitor(stream), + _propertyNode(propertyNode) + { } + virtual void apply(const HLAFixedArrayDataType& dataType) { unsigned numElements = dataType.getNumElements(); @@ -198,6 +288,228 @@ protected: const SGPropertyNode& _propertyNode; }; +class HLAPropertyDataElement::StringDataElement : public HLADataElement { +public: + StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode); + virtual ~StringDataElement(); + + virtual bool encode(HLAEncodeStream& stream) const; + virtual bool decode(HLADecodeStream& stream); + + virtual const HLADataType* getDataType() const; + virtual bool setDataType(const HLADataType* dataType); + +private: + SGSharedPtr _dataType; + SGSharedPtr _propertyNode; +}; + +HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) : + _dataType(dataType), + _propertyNode(propertyNode) +{ +} + +HLAPropertyDataElement::StringDataElement::~StringDataElement() +{ +} + +bool +HLAPropertyDataElement::StringDataElement::encode(HLAEncodeStream& stream) const +{ + StringEncodeVisitor visitor(stream, *_propertyNode); + _dataType->accept(visitor); + return true; +} + +bool +HLAPropertyDataElement::StringDataElement::decode(HLADecodeStream& stream) +{ + StringDecodeVisitor visitor(stream, *_propertyNode); + _dataType->accept(visitor); + return true; +} + +const HLADataType* +HLAPropertyDataElement::StringDataElement::getDataType() const +{ + return _dataType.get(); +} + +bool +HLAPropertyDataElement::StringDataElement::setDataType(const HLADataType* dataType) +{ + if (!dataType) + return false; + const HLAArrayDataType* arrayDataType = dataType->toArrayDataType(); + if (!arrayDataType) + return false; + const HLADataType* elementDataType = arrayDataType->getElementDataType(); + if (!elementDataType) + return false; + if (!elementDataType->toBasicDataType()) + return false; + _dataType = arrayDataType; + 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 _propertyNode; + }; + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + if (dataType.getIsString()) { + _dataElement = new StringDataElement(&dataType, _propertyNode.get()); + } else { + SGSharedPtr arrayDataElement; + arrayDataElement = new HLAArrayDataElement(&dataType); + arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get())); + arrayDataElement->setNumElements(dataType.getNumElements()); + _dataElement = arrayDataElement; + } + } + + virtual void apply(const HLAVariableArrayDataType& dataType) + { + if (dataType.getIsString()) { + _dataElement = new StringDataElement(&dataType, _propertyNode.get()); + } else { + SGSharedPtr 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 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 _propertyNode; + }; + + virtual void apply(const HLAVariantDataType& dataType) + { + SGSharedPtr variantDataElement; + variantDataElement = new HLAVariantDataElement(&dataType); + variantDataElement->setDataElementFactory(new VariantDataElementFactory(_propertyNode.get())); + _dataElement = variantDataElement; + } + + HLADataElement* getDataElement() + { return _dataElement.release(); } + +private: + SGSharedPtr _propertyNode; + SGSharedPtr _dataElement; +}; + HLAPropertyDataElement::HLAPropertyDataElement() { } @@ -225,31 +537,37 @@ HLAPropertyDataElement::~HLAPropertyDataElement() bool HLAPropertyDataElement::encode(HLAEncodeStream& stream) const { - if (!_dataType.valid()) - return false; - if (const SGPropertyNode* propertyNode = getPropertyNode()) { - EncodeVisitor visitor(stream, *propertyNode); - _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 (SGPropertyNode* propertyNode = getPropertyNode()) { - DecodeVisitor visitor(stream, *propertyNode); - _dataType->accept(visitor); } else { - HLADataTypeDecodeVisitor visitor(stream); + HLADataElementFactoryVisitor visitor; _dataType->accept(visitor); + _dataElement = visitor.getDataElement(); + if (_dataElement.valid()) { + return _dataElement->decode(stream); + } else { + HLADataTypeDecodeVisitor visitor(stream); + _dataType->accept(visitor); + return true; + } } - return true; } const HLADataType* @@ -261,24 +579,18 @@ HLAPropertyDataElement::getDataType() const 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* @@ -293,4 +605,26 @@ HLAPropertyDataElement::getPropertyNode() const return _propertyNode.get(); } +HLADataElement* +HLAPropertyDataElement::createDataElement(const SGSharedPtr& dataType, + const SGSharedPtr& propertyNode) +{ + DataElementFactoryVisitor visitor(propertyNode); + dataType->accept(visitor); + SGSharedPtr 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 diff --git a/simgear/hla/HLAPropertyDataElement.hxx b/simgear/hla/HLAPropertyDataElement.hxx index 076d85ba..4354a1d9 100644 --- a/simgear/hla/HLAPropertyDataElement.hxx +++ b/simgear/hla/HLAPropertyDataElement.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -42,10 +42,19 @@ public: const SGPropertyNode* getPropertyNode() const; private: - class DecodeVisitor; - class EncodeVisitor; + HLADataElement* + createDataElement(const SGSharedPtr& dataType, const SGSharedPtr& propertyNode); + + class ScalarDecodeVisitor; + class ScalarEncodeVisitor; + class ScalarDataElement; + class StringDecodeVisitor; + class StringEncodeVisitor; + class StringDataElement; + class DataElementFactoryVisitor; SGSharedPtr _dataType; + SGSharedPtr _dataElement; SGSharedPtr _propertyNode; }; From 64ce231705b3000e18a69c2b610a10288bff1109 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 4 Oct 2011 20:55:44 +0200 Subject: [PATCH 12/32] hla: Initially request update for subscribed unowned attributes. --- simgear/hla/RTIObjectInstance.hxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/simgear/hla/RTIObjectInstance.hxx b/simgear/hla/RTIObjectInstance.hxx index 3edbed60..e3e37b6d 100644 --- a/simgear/hla/RTIObjectInstance.hxx +++ b/simgear/hla/RTIObjectInstance.hxx @@ -133,6 +133,8 @@ public: } else { _attributeData[i].setUpdateEnabled(false); _attributeData[i].setOwned(false); + if (getAttributeSubscribed(i)) + _attributeData[i].setRequestUpdate(true); } } _attributeData.resize(numAttributes); @@ -140,9 +142,13 @@ public: 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); } } } From 70ac6614e8d8243c6f1aebb1cd5b25160499510d Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 4 Oct 2011 21:07:24 +0200 Subject: [PATCH 13/32] hla: Remove interface functions that should not be called explicitly. --- simgear/hla/HLAFederate.hxx | 2 ++ simgear/hla/HLAObjectInstance.cxx | 40 ------------------------------- simgear/hla/HLAObjectInstance.hxx | 10 -------- 3 files changed, 2 insertions(+), 50 deletions(-) diff --git a/simgear/hla/HLAFederate.hxx b/simgear/hla/HLAFederate.hxx index 0775a566..3083903c 100644 --- a/simgear/hla/HLAFederate.hxx +++ b/simgear/hla/HLAFederate.hxx @@ -186,9 +186,11 @@ public: 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; diff --git a/simgear/hla/HLAObjectInstance.cxx b/simgear/hla/HLAObjectInstance.cxx index ae726ee4..1644d938 100644 --- a/simgear/hla/HLAObjectInstance.cxx +++ b/simgear/hla/HLAObjectInstance.cxx @@ -409,26 +409,6 @@ HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePath } } -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() { @@ -467,16 +447,6 @@ HLAObjectInstance::deleteInstance(const RTIData& tag) _rtiObjectInstance->deleteObjectInstance(tag); } -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) { @@ -501,16 +471,6 @@ HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTI _rtiObjectInstance->updateAttributeValues(timeStamp, tag); } -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) { diff --git a/simgear/hla/HLAObjectInstance.hxx b/simgear/hla/HLAObjectInstance.hxx index c0420276..974d2a98 100644 --- a/simgear/hla/HLAObjectInstance.hxx +++ b/simgear/hla/HLAObjectInstance.hxx @@ -52,13 +52,8 @@ public: 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 @@ public: 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); From aa9e91f926de395575a5374642af78c9e3fbb6b5 Mon Sep 17 00:00:00 2001 From: Frederic Bouvier Date: Wed, 5 Oct 2011 08:13:31 +0200 Subject: [PATCH 14/32] Fix win32 build of decode_binobj --- simgear/io/decode_binobj.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/simgear/io/decode_binobj.cxx b/simgear/io/decode_binobj.cxx index 3088393b..af2ae2b9 100644 --- a/simgear/io/decode_binobj.cxx +++ b/simgear/io/decode_binobj.cxx @@ -4,7 +4,10 @@ #include +#ifndef _WIN32 #include +#endif + #include #include From 6485ea4051c6234e7725cd505c99104999db3634 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Wed, 5 Oct 2011 21:03:52 +0200 Subject: [PATCH 15/32] hla: Add flush queue request, fix comments. --- simgear/hla/RTI13Ambassador.hxx | 2 + simgear/hla/RTI13Federate.cxx | 160 ++++++++++++++++++++------------ simgear/hla/RTI13Federate.hxx | 1 + simgear/hla/RTIFederate.hxx | 1 + 4 files changed, 107 insertions(+), 57 deletions(-) diff --git a/simgear/hla/RTI13Ambassador.hxx b/simgear/hla/RTI13Ambassador.hxx index 0723ac47..ecd0af60 100644 --- a/simgear/hla/RTI13Ambassador.hxx +++ b/simgear/hla/RTI13Ambassador.hxx @@ -299,6 +299,8 @@ public: { _rtiAmbassador.timeAdvanceRequest(toFedTime(time)); } void timeAdvanceRequestAvailable(const SGTimeStamp& time) { _rtiAmbassador.timeAdvanceRequestAvailable(toFedTime(time)); } + void flushQueueRequest(const SGTimeStamp& time) + { _rtiAmbassador.flushQueueRequest(toFedTime(time)); } bool queryGALT(SGTimeStamp& timeStamp) { diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx index a9953b93..1eece869 100644 --- a/simgear/hla/RTI13Federate.cxx +++ b/simgear/hla/RTI13Federate.cxx @@ -788,28 +788,28 @@ RTI13Federate::enableTimeConstrained() 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); + 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 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::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); + 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 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; } @@ -833,22 +833,22 @@ RTI13Federate::disableTimeConstrained() _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); + 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 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::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); + 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 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; } @@ -877,34 +877,34 @@ RTI13Federate::enableTimeRegulation(const SGTimeStamp& lookahead) try { _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); + 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 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::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); + 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 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; } @@ -928,22 +928,22 @@ RTI13Federate::disableTimeRegulation() _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); + 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 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::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); + 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 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; } @@ -991,7 +991,7 @@ bool RTI13Federate::timeAdvanceRequest(const SGTimeStamp& timeStamp) { if (!_ambassador.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate."); + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time at unconnected federate."); return false; } @@ -999,34 +999,34 @@ RTI13Federate::timeAdvanceRequest(const SGTimeStamp& timeStamp) _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); + 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 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::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); + 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 resign federation execution: " << e._name << " " << e._reason); + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time: " << e._name << " " << e._reason); return false; } @@ -1037,7 +1037,7 @@ bool RTI13Federate::timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp) { if (!_ambassador.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate."); + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not advance time at unconnected federate."); return false; } @@ -1045,34 +1045,80 @@ RTI13Federate::timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp) _ambassador->timeAdvanceRequestAvailable(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); + 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 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::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); + 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 resign federation execution: " << e._name << " " << e._reason); + 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; } @@ -1261,21 +1307,21 @@ RTI13Federate::getObjectInstance(const std::string& objectInstanceName) 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 class: ObjectInstance not found."); + 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; } } diff --git a/simgear/hla/RTI13Federate.hxx b/simgear/hla/RTI13Federate.hxx index d3cf5ca6..9b8341d2 100644 --- a/simgear/hla/RTI13Federate.hxx +++ b/simgear/hla/RTI13Federate.hxx @@ -65,6 +65,7 @@ public: 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); diff --git a/simgear/hla/RTIFederate.hxx b/simgear/hla/RTIFederate.hxx index 94d692b0..a4c137ff 100644 --- a/simgear/hla/RTIFederate.hxx +++ b/simgear/hla/RTIFederate.hxx @@ -66,6 +66,7 @@ public: 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; From c1f51d5be79ef9e7c746b534347963288b1202fb Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Thu, 6 Oct 2011 16:47:03 +0200 Subject: [PATCH 16/32] Stuart Buchanan: Add additional lighting factors for 3D clouds so you can set the bottom, middle, top, and shade lighting factors. --- simgear/scene/sky/CloudShaderGeometry.cxx | 27 ++++--- simgear/scene/sky/CloudShaderGeometry.hxx | 28 +++---- simgear/scene/sky/newcloud.cxx | 89 +++++++++++++++-------- simgear/scene/sky/newcloud.hxx | 45 +++++++++--- 4 files changed, 121 insertions(+), 68 deletions(-) diff --git a/simgear/scene/sky/CloudShaderGeometry.cxx b/simgear/scene/sky/CloudShaderGeometry.cxx index ed9e94f6..b2ac9252 100644 --- a/simgear/scene/sky/CloudShaderGeometry.cxx +++ b/simgear/scene/sky/CloudShaderGeometry.cxx @@ -110,20 +110,24 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const 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 ); + 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 @@ void CloudShaderGeometry::addSprite(const SGVec3f& p, int tx, int ty, 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 @@ bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr) 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 @@ bool CloudShaderGeometry_writeLocalData(const Object& obj, Output& fw) 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; diff --git a/simgear/scene/sky/CloudShaderGeometry.hxx b/simgear/scene/sky/CloudShaderGeometry.hxx index 78f245ab..1b63f805 100644 --- a/simgear/scene/sky/CloudShaderGeometry.hxx +++ b/simgear/scene/sky/CloudShaderGeometry.hxx @@ -46,14 +46,15 @@ class CloudShaderGeometry : public osg::Drawable 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, float zsc) : - varieties_x(vx), varieties_y(vy), zscale(zsc) + 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 @@ class CloudShaderGeometry : public osg::Drawable 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 @@ class CloudShaderGeometry : public osg::Drawable int texture_index_y; float width; float height; - float shade; - float cloud_height; }; typedef std::vector CloudSpriteList; @@ -88,8 +86,8 @@ class CloudShaderGeometry : public osg::Drawable 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,15 +105,19 @@ class CloudShaderGeometry : public osg::Drawable _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 _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; diff --git a/simgear/scene/sky/newcloud.cxx b/simgear/scene/sky/newcloud.cxx index 3b5321f8..0e9b7325 100644 --- a/simgear/scene/sky/newcloud.cxx +++ b/simgear/scene/sky/newcloud.cxx @@ -60,6 +60,8 @@ using namespace simgear; using namespace osg; +using namespace std; + namespace { @@ -67,24 +69,36 @@ typedef std::map > EffectMap; 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", min_width*2); - min_height = cld_def->getDoubleValue("min-cloud-height-m", 400.0); - max_height = cld_def->getDoubleValue("max-cloud-height-m", min_height*2); - 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*1.5); - min_sprite_height = cld_def->getDoubleValue("min-sprite-height-m", 150); - max_sprite_height = cld_def->getDoubleValue("max-sprite-height-m", min_sprite_height*1.5); + 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); height_map_texture = cld_def->getBoolValue("height-map-texture", false); - bottom_shade = cld_def->getDoubleValue("bottom-shade", 1.0); - zscale = cld_def->getDoubleValue("z-scale", 1.0); + + 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. @@ -167,24 +181,40 @@ osg::ref_ptr SGNewCloud::genCloud() { osg::ref_ptr geode = new EffectGeode; - CloudShaderGeometry* sg = new CloudShaderGeometry(num_textures_x, - num_textures_y, - max_width + max_sprite_width, - max_height + max_sprite_height, - zscale); - // 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++) { @@ -202,8 +232,8 @@ osg::ref_ptr SGNewCloud::genCloud() { y = 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 + height * 0.5f; @@ -235,7 +265,7 @@ osg::ref_ptr SGNewCloud::genCloud() { // Determine the sprite texture indexes. int index_x = (int) floor(sg_random() * num_textures_x); - if (index_x == num_textures_x) { index_x--; } + if (index_x >= num_textures_x) { index_x = num_textures_x - 1; } int index_y = (int) floor(sg_random() * num_textures_y); @@ -243,20 +273,17 @@ osg::ref_ptr SGNewCloud::genCloud() { // 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 + 0.5f) * num_textures_y); + index_y = (int) floor((z / height) * num_textures_y); } - if (index_y == num_textures_y) { index_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); diff --git a/simgear/scene/sky/newcloud.hxx b/simgear/scene/sky/newcloud.hxx index 91db9f60..f6e55733 100644 --- a/simgear/scene/sky/newcloud.hxx +++ b/simgear/scene/sky/newcloud.hxx @@ -47,7 +47,7 @@ public: // Generate a Cloud osg::ref_ptr genCloud (); - static double getDensity(void) + static float getDensity(void) { return sprite_density; } @@ -61,16 +61,37 @@ public: 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; - double zscale; + 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; @@ -78,7 +99,7 @@ private: string texture; osg::Geometry* quad; osg::ref_ptr effect; - static double sprite_density; + static float sprite_density; osg::Geometry* createOrthQuad(float w, float h, int varieties_x, int varieties_y); From eb52f38c473b51c5b1ce907b64c3b83945323524 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Thu, 6 Oct 2011 16:49:09 +0200 Subject: [PATCH 17/32] Stuart Buchanan: A further fix to the cloud placement, to make it more accurate over longer distances. --- simgear/scene/sky/cloudfield.cxx | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/simgear/scene/sky/cloudfield.cxx b/simgear/scene/sky/cloudfield.cxx index 609fe2b3..2b145b57 100644 --- a/simgear/scene/sky/cloudfield.cxx +++ b/simgear/scene/sky/cloudfield.cxx @@ -231,7 +231,7 @@ void SGCloudField::addCloudToTree(osg::ref_ptr t float lon, float lat, float alt, float x, float y) { // Get the base position - SGGeod loc = SGGeod::fromDegFt(lon, lat, alt); + SGGeod loc = SGGeod::fromDegFt(lon, lat, 0.0); // Determine any shift by x/y if ((x != 0.0f) || (y != 0.0f)) { @@ -248,24 +248,24 @@ void SGCloudField::addCloudToTree(osg::ref_ptr t SGGeod base_pos = SGGeod::fromDegFt(lon, lat, 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); } + + // The direct call provides the position at 0 alt, so adjust as required. + loc.setElevationFt(alt); // Work out where this cloud should go in OSG coordinates. SGVec3 cart; SGGeodesy::SGGeodToCart(loc, cart); osg::Vec3f pos = toOsg(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))); if (old_pos == osg::Vec3f(0.0f, 0.0f, 0.0f)) { - // First se tup. + // First setup. SGVec3 fieldcenter; - SGGeodesy::SGGeodToCart(SGGeod::fromDegFt(lon, lat, 0.0f), 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))); field_transform->setPosition(toOsg(fieldcenter)); field_transform->setAttitude(orient); @@ -274,7 +274,8 @@ void SGCloudField::addCloudToTree(osg::ref_ptr t pos = pos - field_transform->getPosition(); - pos = orient.inverse() * pos; + //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 From d9a281c493cac5bef5db95672aef5983beefa4d7 Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 4 Oct 2011 14:04:59 +0100 Subject: [PATCH 18/32] Support for 32-bit vertex indices in BTG files --- simgear/io/sg_binobj.cxx | 1419 +++++++++++++++++--------------------- simgear/io/sg_binobj.hxx | 39 +- 2 files changed, 662 insertions(+), 796 deletions(-) diff --git a/simgear/io/sg_binobj.cxx b/simgear/io/sg_binobj.cxx index 5f7a34d2..7a58321f 100644 --- a/simgear/io/sg_binobj.cxx +++ b/simgear/io/sg_binobj.cxx @@ -33,10 +33,12 @@ #include #include #include // for system() +#include #include #include #include +#include #include #include @@ -85,163 +87,282 @@ private: 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]; + resize(s); } - inline ~sgSimpleBuffer() { - delete [] ptr; + ~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]; - } + 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(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(ptr + offset); + if ( sgIsBigEndian() ) { + sgEndianSwap((uint32_t *) p); + } + + offset += sizeof(float); + return *p; + } + + SGVec2f readVec2f() + { + float* p = reinterpret_cast(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(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(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 +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(buffer); + for (int i=0; i(buffer); + for (int i=0; i +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 +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(vertices[i])); + + if (!normals.empty()) { + write_indice(fp, static_cast(normals[i])); + } + if (!colors.empty()) { + write_indice(fp, static_cast(colors[i])); + } + if (!texCoords.empty()) { + write_indice(fp, static_cast(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(ptr, nbytes, idx_mask, vs, ns, cs, tcs); + } else { + read_indices(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 @@ bool SGBinObject::read_bin( const string& file ) { 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 @@ bool SGBinObject::read_bin( const string& file ) { 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); + // close the file before we return + gzclose(fp); - return false; + return false; } // read creation time @@ -324,673 +445,383 @@ bool SGBinObject::read_bin( const string& file ) { #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; + int16_t v; + sgReadShort( fp, &v ); + nobjects = v; } - // cout << "Total objects to read = " << nobjects << endl; + + //cout << "Total objects to read = " << nobjects << endl; + if ( sgReadError() ) { + cout << "We detected an error while reading the file header" << 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; + 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 - for ( j = 0; j < nproperties; ++j ) { - char prop_type; - sgReadChar( fp, &prop_type ); + //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 ); - 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 ); + 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 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 ); + // 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 ); - 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 ); + // 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 ); - 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 ); + 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 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 ); - } - } + // 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 << "We detected an error while reading object:" << i << endl; + return false; + } } // close the file gzclose(fp); if ( sgReadError() ) { - cout << "We detected an error while reading the file." << endl; - return false; + cout << "We detected an error while reading the file." << 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; + 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) { + if (version == 7) { + write_indices(fp, idx_mask, verts[i], normals[i], colors[i], texCoords[i]); + } else { + write_indices(fp, idx_mask, verts[i], normals[i], colors[i], texCoords[i]); + } + } + + 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 ) + const SGBucket& b ) { - int i, j; - unsigned char idx_mask; - int idx_size; 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) { + 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 << "We detected an error while writing the file." << endl; + return false; } return true; @@ -1001,7 +832,7 @@ bool SGBinObject::write_bin( const string& base, const string& name, // 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 +842,16 @@ bool SGBinObject::write_ascii( const string& base, const string& name, 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 +869,22 @@ bool SGBinObject::write_ascii( const string& base, const string& name, // 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 +892,27 @@ bool SGBinObject::write_ascii( const string& base, const string& name, 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"); + 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; + 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 +923,44 @@ bool SGBinObject::write_ascii( const string& base, const string& name, 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 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"); - } + // 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; - } + start = end; + end = start + 1; + } } // dump triangle groups if ( strips_v.size() > 0 ) { - fprintf(fp, "# triangle strips\n"); + 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; + 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,24 +973,24 @@ bool SGBinObject::write_ascii( const string& base, const string& name, 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 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 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 @@ -1170,3 +1001,21 @@ bool SGBinObject::write_ascii( const string& base, const string& name, return true; } + +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 ); + } +} + diff --git a/simgear/io/sg_binobj.hxx b/simgear/io/sg_binobj.hxx index 7f672640..d594113d 100644 --- a/simgear/io/sg_binobj.hxx +++ b/simgear/io/sg_binobj.hxx @@ -27,29 +27,24 @@ #ifndef _SG_BINOBJ_HXX #define _SG_BINOBJ_HXX +#include // for gzFile #include #include #include -#include +#include -#include -#include - -#include +#include #include - - /** 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 @@ typedef group_list::const_iterator const_group_list_iterator; * - vertex: FLOAT, FLOAT, FLOAT */ class SGBinObject { +private: unsigned short version; SGVec3d gbs_center; @@ -119,6 +115,24 @@ class SGBinObject { 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; } @@ -207,6 +221,9 @@ public: */ 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 * groups come to us sorted by material property. If not, things From 64b6a4ebf25e215e9d3d75e0cce65ee95177fd5d Mon Sep 17 00:00:00 2001 From: Martin Spott Date: Fri, 7 Oct 2011 09:57:09 +0200 Subject: [PATCH 19/32] Add missing header for printf --- simgear/io/decode_binobj.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/simgear/io/decode_binobj.cxx b/simgear/io/decode_binobj.cxx index af2ae2b9..0c4a9922 100644 --- a/simgear/io/decode_binobj.cxx +++ b/simgear/io/decode_binobj.cxx @@ -10,6 +10,7 @@ #include #include +#include #include "sg_binobj.hxx" From 85e58b4a49d3c3b74afed3c766b47b65a6a95a66 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Sat, 8 Oct 2011 17:44:53 +0200 Subject: [PATCH 20/32] hla: for rti13 queue all callbacks. This is to avoid running into the rti13 ambassadors recursion guards. Newer rti standards will not requires this. --- simgear/hla/RTI13Federate.cxx | 453 +++++++++++++++++++++++----- simgear/hla/RTI13ObjectInstance.cxx | 105 ++++--- simgear/hla/RTI13ObjectInstance.hxx | 29 +- simgear/hla/RTIData.hxx | 7 + simgear/hla/RTIObjectClass.cxx | 1 + simgear/hla/RTIObjectInstance.hxx | 81 +---- 6 files changed, 465 insertions(+), 211 deletions(-) diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx index 1eece869..08dbdd86 100644 --- a/simgear/hla/RTI13Federate.cxx +++ b/simgear/hla/RTI13Federate.cxx @@ -41,6 +41,27 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { { } + /// 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) @@ -115,9 +136,21 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { } // 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()) @@ -127,9 +160,21 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { 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()) @@ -151,23 +196,58 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { { } - // 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()) - throw RTI::ObjectClassNotKnown("Federate: discoverObjectInstance()!"); + return; if (!i->second.valid()) return; SGSharedPtr objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, _rtiAmbassador.get(), false); _objectInstanceMap[objectHandle] = objectInstance; - _queueCallbackList.push_back(new DiscoverObjectCallback(i->second, objectInstance, tagToData(tag))); + 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, @@ -175,28 +255,79 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { 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()) - throw RTI::ObjectNotKnown("Reflect attributes for unknown object!"); + return; if (!i->second.valid()) return; - i->second->reflectAttributeValues(attributeValuePairSet, RTI13Ambassador::toTimeStamp(fedTime), tagToData(tag)); + 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()) - throw RTI::ObjectNotKnown("Reflect attributes for unknown object!"); + return; if (!i->second.valid()) return; - i->second->reflectAttributeValues(attributeValuePairSet, tagToData(tag)); + i->second->reflectAttributeValues(attributeHandleDataPairList, tag); } virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters, @@ -216,99 +347,202 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { { } + 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()) - throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!"); + return; if (i->second.valid()) - _queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag))); + 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()) - throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!"); + return; if (i->second.valid()) - _queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag))); + 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 _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& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Attributes in scope for unknown object!"); + 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& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Attributes in scope for unknown object!"); + 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& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Reflect attributes for unknown object!"); + 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& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Turn on attributes for unknown object!"); + 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& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Turn off attributes for unknown object!"); + 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, @@ -316,30 +550,50 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::AttributeAlreadyOwned, RTI::AttributeNotPublished, RTI::FederateInternalError) + { _queueCallbackList.push_back(new RequestAttributeOwnershipAssumptionCallback(objectHandle, attributes, tagToData(tag))); } + void requestAttributeOwnershipAssumptionCallback(RTI::ObjectHandle objectHandle, std::vector& attributes, const RTIData& tag) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("requestAttributeOwnershipAssumption for unknown object!"); + return; if (!i->second.valid()) return; - i->second->requestAttributeOwnershipAssumption(attributes, tagToData(tag)); + 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& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("attributeOwnershipDivestitureNotification for unknown object!"); + 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, @@ -347,95 +601,174 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::AttributeAlreadyOwned, RTI::AttributeNotPublished, RTI::FederateInternalError) + { _queueCallbackList.push_back(new AttributeOwnershipAcquisitionNotificationCallback(objectHandle, attributes)); } + void attributeOwnershipAcquisitionNotificationCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("attributeOwnershipAcquisitionNotification for unknown object!"); + 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& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("attributeOwnershipUnavailable for unknown object!"); + 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& attributes, const RTIData& tag) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("requestAttributeOwnershipRelease for unknown object!"); + return; if (!i->second.valid()) return; - i->second->requestAttributeOwnershipRelease(attributes, tagToData(tag)); + 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& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("confirmAttributeOwnershipAcquisitionCancellation for unknown object!"); + 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()) - throw RTI::ObjectNotKnown("informAttributeOwnership for unknown object!"); + 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()) - throw RTI::ObjectNotKnown("attributeIsNotOwned for unknown object!"); + 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()) - throw RTI::ObjectNotKnown("attributeOwnedByRTI for unknown object!"); + return; if (!i->second.valid()) return; i->second->attributeOwnedByRTI(attributeHandle); @@ -448,8 +781,7 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::FederateInternalError) { _timeRegulationEnabled = true; - _federateTime = RTI13Ambassador::toTimeStamp(fedTime); - SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeRegulationEnabled: " << _federateTime); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeRegulationEnabled: " << RTI13Ambassador::toTimeStamp(fedTime)); } virtual void timeConstrainedEnabled(const RTI::FedTime& fedTime) @@ -458,8 +790,7 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::FederateInternalError) { _timeConstrainedEnabled = true; - _federateTime = RTI13Ambassador::toTimeStamp(fedTime); - SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeConstrainedEnabled: " << _federateTime); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeConstrainedEnabled: " << RTI13Ambassador::toTimeStamp(fedTime)); } virtual void timeAdvanceGrant(const RTI::FedTime& fedTime) @@ -467,9 +798,8 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::TimeAdvanceWasNotInProgress, RTI::FederateInternalError) { - _federateTime = RTI13Ambassador::toTimeStamp(fedTime); _timeAdvancePending = false; - SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeAdvanceGrant: " << _federateTime); + // SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeAdvanceGrant: " << RTI13Ambassador::toTimeStamp(fedTime)); } virtual void requestRetraction(RTI::EventRetractionHandle eventRetractionHandle) @@ -483,7 +813,8 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { void processQueues() { while (!_queueCallbackList.empty()) { - (*_queueCallbackList.front())(); + (*_queueCallbackList.front())(*this); + // _queueCallbackListPool.splice(); _queueCallbackList.pop_front(); } } @@ -499,46 +830,6 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { return true; } - /// 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 DiscoverObjectCallback : public QueueCallback { - public: - DiscoverObjectCallback(SGSharedPtr objectClass, SGSharedPtr objectInstance, const RTIData& tag) : - _objectClass(objectClass), - _objectInstance(objectInstance), - _tag(tag) - { } - virtual void operator()() - { - _objectClass->discoverInstance(_objectInstance.get(), _tag); - _objectInstance->requestObjectAttributeValueUpdate(); - } - private: - SGSharedPtr _objectClass; - SGSharedPtr _objectInstance; - RTIData _tag; - }; - class RemoveObjectCallback : public QueueCallback { - public: - RemoveObjectCallback(SGSharedPtr objectInstance, const RTIData& tag) : - _objectInstance(objectInstance), - _tag(tag) - { } - virtual void operator()() - { - _objectInstance->removeInstance(_tag); - } - private: - SGSharedPtr _objectInstance; - RTIData _tag; - }; - // The rtiambassador to issue requests SGSharedPtr _rtiAmbassador; @@ -550,6 +841,19 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { // That is to make sure we do not call recursively into the RTI typedef std::list > 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 > ObjectInstanceMap; @@ -563,7 +867,6 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { bool _timeRegulationEnabled; bool _timeConstrainedEnabled; bool _timeAdvancePending; - SGTimeStamp _federateTime; private: const RTIData& tagToData(const char* tag) diff --git a/simgear/hla/RTI13ObjectInstance.cxx b/simgear/hla/RTI13ObjectInstance.cxx index 723f9b17..f8ba657f 100644 --- a/simgear/hla/RTI13ObjectInstance.cxx +++ b/simgear/hla/RTI13ObjectInstance.cxx @@ -177,47 +177,56 @@ RTI13ObjectInstance::localDeleteObjectInstance() } 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; + 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); } - RTIObjectInstance::reflectAttributeValues(updateList.front()._indexDataPairList, tag); // Return the update data back to the pool - putUpdateToPool(updateList); + putDataToPool(indexDataPairList); } void -RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag) +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; + getDataFromPool(indexDataPairList); + indexDataPairList.back().first = index; + indexDataPairList.back().second.swap(i->second); } - scheduleUpdates(timeStamp, updateList); + 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 @@ -273,12 +282,12 @@ RTI13ObjectInstance::requestObjectAttributeValueUpdate() } void -RTI13ObjectInstance::provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::provideAttributeValueUpdate(const std::vector& 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); } } @@ -400,72 +409,72 @@ RTI13ObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const R } void -RTI13ObjectInstance::attributesInScope(const RTI::AttributeHandleSet& attributeHandleSet) +RTI13ObjectInstance::attributesInScope(const std::vector& attributeHandleSet) { - RTI::ULong numAttribs = attributeHandleSet.size(); + 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) +RTI13ObjectInstance::attributesOutOfScope(const std::vector& attributeHandleSet) { - RTI::ULong numAttribs = attributeHandleSet.size(); + 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) +RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const std::vector& attributeHandleSet) { - RTI::ULong numAttribs = attributeHandleSet.size(); + 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) +RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const std::vector& attributeHandleSet) { - RTI::ULong numAttribs = attributeHandleSet.size(); + 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) +RTI13ObjectInstance::requestAttributeOwnershipAssumption(const std::vector& attributes, const RTIData& tag) { } void -RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const std::vector& attributes) { } void -RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const std::vector& attributes) { } void -RTI13ObjectInstance::attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::attributeOwnershipUnavailable(const std::vector& attributes) { } void -RTI13ObjectInstance::requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag) +RTI13ObjectInstance::requestAttributeOwnershipRelease(const std::vector& attributes, const RTIData& tag) { } void -RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const std::vector& attributes) { } diff --git a/simgear/hla/RTI13ObjectInstance.hxx b/simgear/hla/RTI13ObjectInstance.hxx index 654bff92..38fd92b2 100644 --- a/simgear/hla/RTI13ObjectInstance.hxx +++ b/simgear/hla/RTI13ObjectInstance.hxx @@ -37,6 +37,9 @@ namespace simgear { class RTI13Ambassador; class RTI13ObjectClass; +typedef std::pair RTI13AttributeHandleDataPair; +typedef std::list RTI13AttributeHandleDataPairList; + class RTI13ObjectInstance : public RTIObjectInstance { public: RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned); @@ -65,27 +68,27 @@ public: 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& 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& attributes); + void attributesOutOfScope(const std::vector& attributes); - void turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributes); - void turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributes); + void turnUpdatesOnForObjectInstance(const std::vector& attributes); + void turnUpdatesOffForObjectInstance(const std::vector& 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& attributes, const RTIData& tag); + void attributeOwnershipDivestitureNotification(const std::vector& attributes); + void attributeOwnershipAcquisitionNotification(const std::vector& attributes); + void attributeOwnershipUnavailable(const std::vector& attributes); + void requestAttributeOwnershipRelease(const std::vector& attributes, const RTIData& tag); + void confirmAttributeOwnershipAcquisitionCancellation(const std::vector& attributes); void informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle); void attributeIsNotOwned(RTI::AttributeHandle attributeHandle); void attributeOwnedByRTI(RTI::AttributeHandle attributeHandle); diff --git a/simgear/hla/RTIData.hxx b/simgear/hla/RTIData.hxx index dff66dbf..2dc32b06 100644 --- a/simgear/hla/RTIData.hxx +++ b/simgear/hla/RTIData.hxx @@ -115,6 +115,13 @@ public: 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) diff --git a/simgear/hla/RTIObjectClass.cxx b/simgear/hla/RTIObjectClass.cxx index 98618cfc..dceb3029 100644 --- a/simgear/hla/RTIObjectClass.cxx +++ b/simgear/hla/RTIObjectClass.cxx @@ -39,6 +39,7 @@ RTIObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIDat return; } hlaObjectClass->discoverInstance(objectInstance, tag); + objectInstance->requestObjectAttributeValueUpdate(); } void diff --git a/simgear/hla/RTIObjectInstance.hxx b/simgear/hla/RTIObjectInstance.hxx index e3e37b6d..61ff9328 100644 --- a/simgear/hla/RTIObjectInstance.hxx +++ b/simgear/hla/RTIObjectInstance.hxx @@ -60,20 +60,6 @@ public: 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) @@ -241,80 +227,25 @@ protected: // 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 UpdateList; - // The timestamp sorted list of updates - typedef std::map 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) + void getDataFromPool(RTIIndexDataPairList& dataPairList) { - if (_attributeData.size() <= i) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!"); - return; - } - // 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 { From 5ede8c12ba68cf1a0cda6e6d25c76d21a14612e8 Mon Sep 17 00:00:00 2001 From: ThorstenB Date: Tue, 11 Oct 2011 21:28:37 +0200 Subject: [PATCH 21/32] Make SGModelPlacement safe on reinit Remove old model When init is called multiple times (i.e. reinit). Also allow explicit removal of submodel (= init(0) ). --- simgear/scene/model/placement.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/simgear/scene/model/placement.cxx b/simgear/scene/model/placement.cxx index 85284492..8d2ab9f2 100644 --- a/simgear/scene/model/placement.cxx +++ b/simgear/scene/model/placement.cxx @@ -25,6 +25,7 @@ SGModelPlacement::SGModelPlacement () : _selector(new osg::Switch), _transform(new osg::PositionAttitudeTransform) { + _selector->addChild(_transform.get()); } SGModelPlacement::~SGModelPlacement () @@ -34,10 +35,11 @@ SGModelPlacement::~SGModelPlacement () 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); } From e4e31be7d43569a92a5d9fa7e784381b66cbd95a Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 12 Oct 2011 17:01:52 +0100 Subject: [PATCH 22/32] Fix BTG writer for non-included index arrays. --- simgear/io/sg_binobj.cxx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/simgear/io/sg_binobj.cxx b/simgear/io/sg_binobj.cxx index 7a58321f..e01a5286 100644 --- a/simgear/io/sg_binobj.cxx +++ b/simgear/io/sg_binobj.cxx @@ -261,13 +261,13 @@ void write_indices(gzFile fp, unsigned char indexMask, for (unsigned int i=0; i < count; ++i) { write_indice(fp, static_cast(vertices[i])); - if (!normals.empty()) { + if (indexMask & SG_IDX_NORMALS) { write_indice(fp, static_cast(normals[i])); } - if (!colors.empty()) { + if (indexMask & SG_IDX_COLORS) { write_indice(fp, static_cast(colors[i])); } - if (!texCoords.empty()) { + if (indexMask & SG_IDX_TEXCOORDS) { write_indice(fp, static_cast(texCoords[i])); } } @@ -667,6 +667,8 @@ void SGBinObject::write_objects(gzFile fp, int type, const group_list& verts, 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 @@ -692,10 +694,15 @@ void SGBinObject::write_objects(gzFile fp, int type, const group_list& verts, // 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(fp, idx_mask, verts[i], normals[i], colors[i], texCoords[i]); + write_indices(fp, idx_mask, va, na, ca, tca); } else { - write_indices(fp, idx_mask, verts[i], normals[i], colors[i], texCoords[i]); + write_indices(fp, idx_mask, va, na, ca, tca); } } From d37bf8a4ae4473dfc5e86e9f5b38de41512aa985 Mon Sep 17 00:00:00 2001 From: James Turner Date: Fri, 14 Oct 2011 11:37:36 +0100 Subject: [PATCH 23/32] SGPath/Dir extensions to ease file handling in TerraGear. Also a unit-test, shocking. --- simgear/misc/CMakeLists.txt | 5 ++ simgear/misc/path_test.cxx | 142 ++++++++++++++++++++++++++++++++++ simgear/misc/sg_dir.cxx | 103 +++++++++++++++++++++++++ simgear/misc/sg_dir.hxx | 32 ++++++++ simgear/misc/sg_path.cxx | 148 ++++++++++++++++++++++++++++-------- simgear/misc/sg_path.hxx | 59 +++++++++++--- 6 files changed, 450 insertions(+), 39 deletions(-) create mode 100644 simgear/misc/path_test.cxx diff --git a/simgear/misc/CMakeLists.txt b/simgear/misc/CMakeLists.txt index 6b21c7ca..7a06f3bd 100644 --- a/simgear/misc/CMakeLists.txt +++ b/simgear/misc/CMakeLists.txt @@ -41,3 +41,8 @@ target_link_libraries(test_tabbed_values sgmisc) add_executable(test_strings strutils_test.cxx ) add_test(test_strings ${EXECUTABLE_OUTPUT_PATH}/test_strings) target_link_libraries(test_strings sgmisc) + +add_executable(test_path path_test.cxx ) +add_test(test_path ${EXECUTABLE_OUTPUT_PATH}/test_path) +target_link_libraries(test_path sgmisc sgdebug) + diff --git a/simgear/misc/path_test.cxx b/simgear/misc/path_test.cxx new file mode 100644 index 00000000..0c316682 --- /dev/null +++ b/simgear/misc/path_test.cxx @@ -0,0 +1,142 @@ + +#include + +#include + +using std::cout; +using std::cerr; +using std::endl; + +#define COMPARE(a, b) \ + if ((a) != (b)) { \ + cerr << "failed:" << #a << " != " << #b << endl; \ + exit(1); \ + } + +#define VERIFY(a) \ + if (!(a)) { \ + cerr << "failed:" << #a << endl; \ + exit(1); \ + } + +#include +#include + +void test_dir() +{ + simgear::Dir temp = simgear::Dir::tempDir("foo"); + cout << "created:" << temp.path().str() << endl; + + VERIFY(temp.exists()); + VERIFY(temp.path().isDir()); + VERIFY(!temp.path().isFile()); + + SGPath fileInDir = temp.file("foobaz"); + VERIFY(!fileInDir.exists()); + + if (!temp.remove(true)) { + cout << "remove failed!" << endl; + } + + cout << temp.path().modTime() << endl; +} + +int main(int argc, char* argv[]) +{ + SGPath pa; + VERIFY(pa.isNull()); + COMPARE(pa.exists(), false); + +// test basic parsing + SGPath pb("/Foo/bar/something.png"); + COMPARE(pb.str(), std::string("/Foo/bar/something.png")); + COMPARE(strcmp(pb.c_str(), "/Foo/bar/something.png"), 0); + COMPARE(pb.dir(), std::string("/Foo/bar")); + COMPARE(pb.file(), std::string("something.png")); + COMPARE(pb.base(), std::string("/Foo/bar/something")); + COMPARE(pb.file_base(), std::string("something")); + COMPARE(pb.extension(), std::string("png")); + VERIFY(pb.isAbsolute()); + VERIFY(!pb.isRelative()); + +// relative paths + SGPath ra("where/to/begin.txt"); + COMPARE(ra.str(), std::string("where/to/begin.txt")); + COMPARE(ra.dir(), std::string("where/to")); + COMPARE(ra.file(), std::string("begin.txt")); + COMPARE(ra.file_base(), std::string("begin")); + VERIFY(!ra.isAbsolute()); + VERIFY(ra.isRelative()); + +// dots in paths / missing extensions + SGPath pk("/Foo/bar.dot/thing"); + COMPARE(pk.dir(), std::string("/Foo/bar.dot")); + COMPARE(pk.file(), std::string("thing")); + COMPARE(pk.base(), std::string("/Foo/bar.dot/thing")); + COMPARE(pk.file_base(), std::string("thing")); + COMPARE(pk.extension(), std::string()); + +// multiple file extensions + SGPath pj("/Foo/zot.dot/thing.tar.gz"); + COMPARE(pj.dir(), std::string("/Foo/zot.dot")); + COMPARE(pj.file(), std::string("thing.tar.gz")); + COMPARE(pj.base(), std::string("/Foo/zot.dot/thing")); + COMPARE(pj.file_base(), std::string("thing")); + COMPARE(pj.extension(), std::string("gz")); + COMPARE(pj.complete_lower_extension(), std::string("tar.gz")); + +// path fixing + SGPath rd("where\\to\\begin.txt"); + COMPARE(rd.str(), std::string("where/to/begin.txt")); + +// test modification +// append + SGPath d1("/usr/local"); + SGPath pc = d1; + COMPARE(pc.str(), std::string("/usr/local")); + pc.append("include"); + + COMPARE(pc.str(), std::string("/usr/local/include")); + COMPARE(pc.file(), std::string("include")); + +// add + pc.add("/opt/local"); + COMPARE(pc.str(), std::string("/usr/local/include/:/opt/local")); + +// concat + SGPath pd = pb; + pd.concat("-1"); + COMPARE(pd.str(), std::string("/Foo/bar/something.png-1")); + +// create with relative path + SGPath rb(d1, "include/foo"); + COMPARE(rb.str(), std::string("/usr/local/include/foo")); + VERIFY(rb.isAbsolute()); + +// lower-casing of file extensions + SGPath extA("FOO.ZIP"); + COMPARE(extA.base(), "FOO"); + COMPARE(extA.extension(), "ZIP"); + COMPARE(extA.lower_extension(), "zip"); + COMPARE(extA.complete_lower_extension(), "zip"); + + SGPath extB("BAH/FOO.HTML.GZ"); + COMPARE(extB.extension(), "GZ"); + COMPARE(extB.base(), "BAH/FOO"); + COMPARE(extB.lower_extension(), "gz"); + COMPARE(extB.complete_lower_extension(), "html.gz"); +#ifdef _WIN32 + COMPARE(d1.str_native(), std::string("\\usr\\local")); + + SGPath winAbs("C:\\Windows\\System32"); + COMPARE(winAbs.str(), std::string("C:/Windows/System32")); +#else + COMPARE(d1.str_native(), std::string("/usr/local")); +#endif + + test_dir(); + + cout << "all tests passed OK" << endl; + return 0; // passed +} + diff --git a/simgear/misc/sg_dir.cxx b/simgear/misc/sg_dir.cxx index 95929229..99ede3e4 100644 --- a/simgear/misc/sg_dir.cxx +++ b/simgear/misc/sg_dir.cxx @@ -24,27 +24,59 @@ #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN # include +# include #else # include # include +# include +# include +# include #endif #include +#include #include #include +using std::string; + namespace simgear { Dir::Dir(const SGPath& path) : _path(path) { + _path.set_cached(false); // disable caching, so create/remove work } Dir::Dir(const Dir& rel, const SGPath& relPath) : _path(rel.file(relPath.str())) { + _path.set_cached(false); // disable caching, so create/remove work +} + +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) +{ + 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; } PathList Dir::children(int types, const std::string& nameFilter) const @@ -175,8 +207,79 @@ bool Dir::exists() const 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.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 diff --git a/simgear/misc/sg_dir.hxx b/simgear/misc/sg_dir.hxx index 0ebc2bf7..707053ab 100644 --- a/simgear/misc/sg_dir.hxx +++ b/simgear/misc/sg_dir.hxx @@ -31,6 +31,10 @@ #include #include +#ifdef _MSC_VER + typedef int mode_t; +#endif + namespace simgear { typedef std::vector PathList; @@ -38,6 +42,13 @@ namespace simgear class Dir { public: + 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,10 +64,31 @@ namespace simgear 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; }; diff --git a/simgear/misc/sg_path.cxx b/simgear/misc/sg_path.cxx index 20dd4fbc..53504a20 100644 --- a/simgear/misc/sg_path.cxx +++ b/simgear/misc/sg_path.cxx @@ -28,13 +28,16 @@ #include #include #include +#include + #ifdef _WIN32 # include #endif #include "sg_path.hxx" -using std::string; +#include +using std::string; /** * define directory path separators @@ -58,14 +61,14 @@ 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; - } + // for windoze, don't replace the ":" for the second character + if ( i == 1 ) { + continue; + } #endif - if ( path[i] == sgDirPathSepBad ) { - path[i] = sgDirPathSep; - } + if ( path[i] == sgDirPathSepBad ) { + path[i] = sgDirPathSep; + } } } @@ -73,7 +76,8 @@ SGPath::fix() // default constructor SGPath::SGPath() : path(""), - _cached(false) + _cached(false), + _cacheEnabled(true) { } @@ -81,7 +85,8 @@ SGPath::SGPath() // create a path based on "path" SGPath::SGPath( const std::string& p ) : path(p), - _cached(false) + _cached(false), + _cacheEnabled(true) { fix(); } @@ -89,7 +94,8 @@ SGPath::SGPath( const std::string& p ) // 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,9 +104,11 @@ SGPath::SGPath( const SGPath& p, const std::string& r ) 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) { } @@ -108,9 +116,11 @@ 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 +136,20 @@ void SGPath::set( const string& p ) { _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; + path = p; } else { - if ( p[0] != sgDirPathSep ) { - path += sgDirPathSep; - } - path += p; + if ( p[0] != sgDirPathSep ) { + path += sgDirPathSep; + } + path += p; } fix(); _cached = false; @@ -151,9 +165,9 @@ void SGPath::add( const string& p ) { // path separator void SGPath::concat( const string& p ) { if ( path.size() == 0 ) { - path = p; + path = p; } else { - path += p; + path += p; } fix(); _cached = false; @@ -164,9 +178,9 @@ void SGPath::concat( const string& p ) { string SGPath::file() const { int index = path.rfind(sgDirPathSep); if (index >= 0) { - return path.substr(index + 1); + return path.substr(index + 1); } else { - return ""; + return ""; } } @@ -175,20 +189,45 @@ string SGPath::file() const { string SGPath::dir() const { int index = path.rfind(sgDirPathSep); if (index >= 0) { - return path.substr(0, index); + return path.substr(0, index); } else { - return ""; + 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); + unsigned int index = path.rfind(sgDirPathSep); + if (index == string::npos) { + index = 0; // no separator in the name } else { - return ""; + ++index; // skip past the separator } + +// find the first dot after the final separator + unsigned int firstDot = path.find(".", index); + if (firstDot == string::npos) { + return path; // no extension, return whole path + } + + return path.substr(0, firstDot); +} + +string SGPath::file_base() const +{ + unsigned int index = path.rfind(sgDirPathSep); + if (index == string::npos) { + index = 0; // no separator in the name + } else { + ++index; // skip past the separator + } + + unsigned int 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 +236,36 @@ string SGPath::base() const { string SGPath::extension() const { int index = path.rfind("."); if ((index >= 0) && (path.find("/", index) == string::npos)) { - return path.substr(index + 1); + return path.substr(index + 1); } else { - return ""; + return ""; + } +} + +string SGPath::lower_extension() const { + return boost::to_lower_copy(extension()); +} + +string SGPath::complete_lower_extension() const +{ + unsigned int index = path.rfind(sgDirPathSep); + if (index == string::npos) { + index = 0; // no separator in the name + } else { + ++index; // skip past the separator + } + + int firstDot = path.find(".", index); + if ((firstDot >= 0) && (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 +281,7 @@ void SGPath::validate() const _exists = true; _isFile = ((S_IFREG & buf.st_mode ) !=0); _isDir = ((S_IFDIR & buf.st_mode ) !=0); + _modTime = buf.st_mtime; } #else @@ -232,6 +293,7 @@ void SGPath::validate() const _exists = true; _isFile = ((S_ISREG(buf.st_mode )) != 0); _isDir = ((S_ISDIR(buf.st_mode )) != 0); + _modTime = buf.st_mtime; } #endif @@ -383,3 +445,29 @@ std::string SGPath::str_native() const 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); +} + diff --git a/simgear/misc/sg_path.hxx b/simgear/misc/sg_path.hxx index 0684d570..27b375d9 100644 --- a/simgear/misc/sg_path.hxx +++ b/simgear/misc/sg_path.hxx @@ -32,6 +32,7 @@ #include #include +#include #include @@ -49,10 +50,6 @@ class SGPath { -private: - - std::string path; - public: /** Default constructor */ @@ -86,6 +83,15 @@ public: 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. @@ -123,12 +129,33 @@ public: */ 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,16 +203,30 @@ public: * check for default constructed path */ bool isNull() const; + + /** + * delete the file, if possible + */ + bool remove(); + + /** + * modification time of the file + */ + time_t modTime() const; 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; }; From d1d8c68bf161f151adf73a724cc54be7991090db Mon Sep 17 00:00:00 2001 From: James Turner Date: Fri, 14 Oct 2011 12:05:31 +0100 Subject: [PATCH 24/32] Missing include on Linux --- simgear/misc/path_test.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/simgear/misc/path_test.cxx b/simgear/misc/path_test.cxx index 0c316682..d4a490c4 100644 --- a/simgear/misc/path_test.cxx +++ b/simgear/misc/path_test.cxx @@ -2,6 +2,7 @@ #include #include +#include using std::cout; using std::cerr; From 33970663435dd1a12941b017739285341205acf4 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 31 Aug 2011 07:26:11 -0700 Subject: [PATCH 25/32] One more Linux compile fix. --- simgear/misc/path_test.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/simgear/misc/path_test.cxx b/simgear/misc/path_test.cxx index d4a490c4..2d789e64 100644 --- a/simgear/misc/path_test.cxx +++ b/simgear/misc/path_test.cxx @@ -3,6 +3,7 @@ #include #include +#include using std::cout; using std::cerr; From 086a30e61aa153008bd403c79cd1bff3ad594179 Mon Sep 17 00:00:00 2001 From: James Turner Date: Fri, 14 Oct 2011 19:28:21 +0100 Subject: [PATCH 26/32] Add default constructor to simgear::Dir --- simgear/misc/sg_dir.cxx | 4 ++++ simgear/misc/sg_dir.hxx | 2 ++ 2 files changed, 6 insertions(+) diff --git a/simgear/misc/sg_dir.cxx b/simgear/misc/sg_dir.cxx index 99ede3e4..e1a2610f 100644 --- a/simgear/misc/sg_dir.cxx +++ b/simgear/misc/sg_dir.cxx @@ -44,6 +44,10 @@ using std::string; namespace simgear { +Dir::Dir() +{ +} + Dir::Dir(const SGPath& path) : _path(path) { diff --git a/simgear/misc/sg_dir.hxx b/simgear/misc/sg_dir.hxx index 707053ab..7befbc8c 100644 --- a/simgear/misc/sg_dir.hxx +++ b/simgear/misc/sg_dir.hxx @@ -42,6 +42,8 @@ namespace simgear class Dir { public: + Dir(); + static Dir current(); /** From bc9b3f6ff1fcc5caa67c07ad99f971c0faacf91a Mon Sep 17 00:00:00 2001 From: James Turner Date: Fri, 14 Oct 2011 21:57:34 +0100 Subject: [PATCH 27/32] Unit test for SGBinObj, and fix a bug in large-indice handling the test revealed. --- simgear/io/CMakeLists.txt | 12 +- simgear/io/sg_binobj.cxx | 4 +- simgear/io/test_binobj.cxx | 257 +++++++++++++++++++++++++++++++++++++ 3 files changed, 271 insertions(+), 2 deletions(-) create mode 100644 simgear/io/test_binobj.cxx diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index 01560b39..84acd3f0 100644 --- a/simgear/io/CMakeLists.txt +++ b/simgear/io/CMakeLists.txt @@ -65,4 +65,14 @@ target_link_libraries(decode_binobj ${WINSOCK_LIBRARY} ${ZLIB_LIBRARY} ${RT_LIBRARY}) - \ No newline at end of file + +add_executable(test_binobj test_binobj.cxx) +target_link_libraries(test_binobj + sgio sgbucket sgstructure sgthreads sgtiming sgmisc sgdebug + ${CMAKE_THREAD_LIBS_INIT} + ${WINSOCK_LIBRARY} + ${ZLIB_LIBRARY} + ${RT_LIBRARY}) + +add_test(binobj ${EXECUTABLE_OUTPUT_PATH}/test_binobj) + \ No newline at end of file diff --git a/simgear/io/sg_binobj.cxx b/simgear/io/sg_binobj.cxx index e01a5286..54f3b8de 100644 --- a/simgear/io/sg_binobj.cxx +++ b/simgear/io/sg_binobj.cxx @@ -752,7 +752,9 @@ bool SGBinObject::write_bin_file(const SGPath& file) cout << "tex coords = " << texcoords.size() << endl; version = 10; - if (wgs84_nodes.size() < 0xffff) { + if ((wgs84_nodes.size() < 0xffff) && + (normals.size() < 0xffff) && + (texcoords.size() < 0xffff)) { version = 7; // use smaller indices if possible } diff --git a/simgear/io/test_binobj.cxx b/simgear/io/test_binobj.cxx new file mode 100644 index 00000000..20c7ad33 --- /dev/null +++ b/simgear/io/test_binobj.cxx @@ -0,0 +1,257 @@ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#include + +#include + +#include "sg_binobj.hxx" + +using std::cout; +using std::cerr; +using std::endl; +using std::string; + +#define COMPARE(a, b) \ + if ((a) != (b)) { \ + cerr << "failed:" << #a << " != " << #b << endl; \ + cerr << "\tgot:" << a << endl; \ + exit(1); \ + } + +#define VERIFY(a) \ + if (!(a)) { \ + cerr << "failed:" << #a << endl; \ + exit(1); \ + } + +void generate_points(int count, std::vector& vec) +{ + for (int i=0; i& vec) +{ + for (int i=0; i& vec) +{ + for (int i=0; i& b) +{ + for (unsigned int i=1; i points; + generate_points(1024, points); + std::vector normals; + generate_normals(1024, normals); + std::vector texCoords; + generate_tcs(10000, texCoords); + + basic.set_wgs84_nodes(points); + basic.set_normals(normals); + basic.set_texcoords(texCoords); + + bool ok = basic.write_bin_file(path); + VERIFY( ok ); + + SGBinObject rd; + ok = rd.read_bin(path.str()) ; + VERIFY( ok); + COMPARE(rd.get_version(), 7); // should be version 7 since indices are < 2^16 + COMPARE(rd.get_gbs_center(), center); + COMPARE(rd.get_gbs_radius(), 12345); + COMPARE(rd.get_wgs84_nodes().size(), points.size()); + + comparePoints(rd, points); + compareTexCoords(rd, texCoords); +} + +void test_many_tcs() +{ + SGBinObject basic; + SGPath path(simgear::Dir::current().file("many_tex.btg.gz")); + + SGVec3d center(1, 2, 3); + basic.set_gbs_center(center); + basic.set_gbs_radius(12345); + + std::vector points; + generate_points(10000, points); + std::vector normals; + generate_normals(1024, normals); + std::vector texCoords; + generate_tcs(100000, texCoords); + + basic.set_wgs84_nodes(points); + basic.set_normals(normals); + basic.set_texcoords(texCoords); + + generate_tris(basic, 20000); + + bool ok = basic.write_bin_file(path); + VERIFY( ok ); + + SGBinObject rd; + ok = rd.read_bin(path.str()) ; + VERIFY( ok); + COMPARE(rd.get_version(), 10); // should be version 10 since indices are > 2^16 + COMPARE(rd.get_wgs84_nodes().size(), points.size()); + COMPARE(rd.get_texcoords().size(), texCoords.size()); + + comparePoints(rd, points); + compareTexCoords(rd, texCoords); + compareTris(basic, rd); +} + +void test_big() +{ + SGBinObject basic; + SGPath path(simgear::Dir::current().file("big.btg.gz")); + + SGVec3d center(1, 2, 3); + basic.set_gbs_center(center); + basic.set_gbs_radius(12345); + + std::vector points; + generate_points(200000, points); + std::vector normals; + generate_normals(1024, normals); + std::vector texCoords; + generate_tcs(300000, texCoords); + + basic.set_wgs84_nodes(points); + basic.set_normals(normals); + basic.set_texcoords(texCoords); + + generate_tris(basic, 200000); + + bool ok = basic.write_bin_file(path); + VERIFY( ok ); + + SGBinObject rd; + ok = rd.read_bin(path.str()) ; + VERIFY( ok); + COMPARE(rd.get_version(), 10); // should be version 10 since indices are > 2^16 + COMPARE(rd.get_wgs84_nodes().size(), points.size()); + COMPARE(rd.get_texcoords().size(), texCoords.size()); + + comparePoints(rd, points); + compareTexCoords(rd, texCoords); + compareTris(basic, rd); +} + +int main(int argc, char* argv[]) +{ + test_empty(); + test_basic(); + test_many_tcs(); + test_big(); + + return 0; +} From 04a47dfb8d96a58352b16658eb12d4aed90a97e8 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 15 Oct 2011 02:06:35 +0100 Subject: [PATCH 28/32] Use mkdtemp where available, avoiding linker warnings about dangerous tempnam --- CMakeLists.txt | 2 +- simgear/misc/sg_dir.cxx | 20 ++++++++++++++++++++ simgear/simgear_config_cmake.h.in | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e2e8ebe..922d653f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,7 +130,7 @@ check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) check_function_exists(ftime HAVE_FTIME) check_function_exists(timegm HAVE_TIMEGM) check_function_exists(rint HAVE_RINT) - +check_function_exists(mkdtemp HAVE_MKDTEMP) if(HAVE_UNISTD_H) set(CMAKE_REQUIRED_INCLUDES ${CMAKE_INCLUDE_PATH}) diff --git a/simgear/misc/sg_dir.cxx b/simgear/misc/sg_dir.cxx index e1a2610f..95f9949d 100644 --- a/simgear/misc/sg_dir.cxx +++ b/simgear/misc/sg_dir.cxx @@ -18,6 +18,9 @@ // // $Id$ +#ifdef HAVE_CONFIG_H +# include +#endif #include @@ -74,6 +77,22 @@ Dir Dir::current() Dir Dir::tempDir(const std::string& templ) { +#ifdef HAVE_MKDTEMP + char buf[1024]; + 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)) { @@ -81,6 +100,7 @@ Dir Dir::tempDir(const std::string& templ) } return t; +#endif } PathList Dir::children(int types, const std::string& nameFilter) const diff --git a/simgear/simgear_config_cmake.h.in b/simgear/simgear_config_cmake.h.in index bfb4b1b9..3d132306 100644 --- a/simgear/simgear_config_cmake.h.in +++ b/simgear/simgear_config_cmake.h.in @@ -11,6 +11,7 @@ #cmakedefine HAVE_TIMEGM #cmakedefine HAVE_ISNAN #cmakedefine HAVE_WINDOWS_H +#cmakedefine HAVE_MKDTEMP #cmakedefine HAVE_SVN_CLIENT_H #cmakedefine HAVE_LIBSVN_CLIENT_1 From 09b0dd2b2d7d934c1d4059cb2cbd3b4fcbb7872f Mon Sep 17 00:00:00 2001 From: Frederic Bouvier Date: Sat, 15 Oct 2011 09:42:15 +0200 Subject: [PATCH 29/32] Fix windows build --- simgear/io/test_binobj.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/simgear/io/test_binobj.cxx b/simgear/io/test_binobj.cxx index 20c7ad33..50d60913 100644 --- a/simgear/io/test_binobj.cxx +++ b/simgear/io/test_binobj.cxx @@ -9,6 +9,10 @@ #include #include +#ifdef _MSC_VER +# define random rand +#endif + #include #include "sg_binobj.hxx" From bcf7ed501d02d57cc8038c270db380a01a23da72 Mon Sep 17 00:00:00 2001 From: Csaba Halasz Date: Sun, 16 Oct 2011 14:00:39 +0200 Subject: [PATCH 30/32] Compile fix: add this-> in SGExpression.hxx due to two-phase name lookup (reported by gcc 4.7) --- simgear/structure/SGExpression.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/structure/SGExpression.hxx b/simgear/structure/SGExpression.hxx index a2525fc7..420a9045 100644 --- a/simgear/structure/SGExpression.hxx +++ b/simgear/structure/SGExpression.hxx @@ -1248,7 +1248,7 @@ namespace simgear ConvertExpression() {} ConvertExpression(::SGExpression* expr0) { - addOperand(expr0); + this->addOperand(expr0); } virtual void eval(T& value, const simgear::expression::Binding* b) const { From 9cdf5ab9a147f41262f522bd1afd1e797d733c3b Mon Sep 17 00:00:00 2001 From: James Turner Date: Mon, 17 Oct 2011 09:50:21 +0100 Subject: [PATCH 31/32] Add another helper to strutils, to compare version strings. --- simgear/misc/strutils.cxx | 20 ++++++++++++++++++++ simgear/misc/strutils.hxx | 8 ++++++++ simgear/misc/strutils_test.cxx | 10 ++++++++++ 3 files changed, 38 insertions(+) diff --git a/simgear/misc/strutils.cxx b/simgear/misc/strutils.cxx index 8bd33b7f..5a669a6b 100644 --- a/simgear/misc/strutils.cxx +++ b/simgear/misc/strutils.cxx @@ -259,6 +259,26 @@ namespace simgear { return result; } + int compare_versions(const string& v1, const string& v2) + { + vector v1parts(split(v1, ".")); + vector 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(); + } + + } // end namespace strutils } // end namespace simgear diff --git a/simgear/misc/strutils.hxx b/simgear/misc/strutils.hxx index 1a0859d5..091ba823 100644 --- a/simgear/misc/strutils.hxx +++ b/simgear/misc/strutils.hxx @@ -127,6 +127,14 @@ namespace simgear { * 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 diff --git a/simgear/misc/strutils_test.cxx b/simgear/misc/strutils_test.cxx index f6e08e08..8369f4ea 100644 --- a/simgear/misc/strutils_test.cxx +++ b/simgear/misc/strutils_test.cxx @@ -53,6 +53,16 @@ int main (int ac, char ** av) COMPARE(to_int("0000000"), 0); COMPARE(to_int("-10000"), -10000); + VERIFY(compare_versions("1.0.12", "1.1") < 0); + VERIFY(compare_versions("1.1", "1.0.12") > 0); + VERIFY(compare_versions("10.6.7", "10.6.7") == 0); + VERIFY(compare_versions("2.0", "2.0.99") < 0); + VERIFY(compare_versions("99", "99") == 0); + VERIFY(compare_versions("99", "98") > 0); + +// since we compare numerically, leasing zeros shouldn't matter + VERIFY(compare_versions("0.06.7", "0.6.07") == 0); + cout << "all tests passed successfully!" << endl; return 0; } From 8cb716fe8e411a8cc8e4fe868e9718509754a673 Mon Sep 17 00:00:00 2001 From: James Turner Date: Mon, 17 Oct 2011 09:50:35 +0100 Subject: [PATCH 32/32] std:: namespace fixes. --- simgear/scene/tsync/terrasync.cxx | 1 + simgear/scene/tsync/terrasync.hxx | 2 +- simgear/sound/soundmgr_openal.cxx | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/simgear/scene/tsync/terrasync.cxx b/simgear/scene/tsync/terrasync.cxx index 357390cc..0f99d4e5 100644 --- a/simgear/scene/tsync/terrasync.cxx +++ b/simgear/scene/tsync/terrasync.cxx @@ -86,6 +86,7 @@ #endif using namespace simgear; +using namespace std; const char* rsync_cmd = "rsync --verbose --archive --delete --perms --owner --group"; diff --git a/simgear/scene/tsync/terrasync.hxx b/simgear/scene/tsync/terrasync.hxx index 89ce5a7f..7e6e0cb1 100644 --- a/simgear/scene/tsync/terrasync.hxx +++ b/simgear/scene/tsync/terrasync.hxx @@ -54,7 +54,7 @@ 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; diff --git a/simgear/sound/soundmgr_openal.cxx b/simgear/sound/soundmgr_openal.cxx index 3a0b2979..f0c08eb2 100644 --- a/simgear/sound/soundmgr_openal.cxx +++ b/simgear/sound/soundmgr_openal.cxx @@ -47,6 +47,7 @@ #include using std::string; +using std::vector; extern bool isNaN(float *v);