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/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/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 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/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/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; } diff --git a/simgear/hla/HLAObjectInstance.cxx b/simgear/hla/HLAObjectInstance.cxx index 0324d328..1644d938 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; }; @@ -413,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() { @@ -471,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) { @@ -505,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); diff --git a/simgear/hla/HLAPropertyDataElement.cxx b/simgear/hla/HLAPropertyDataElement.cxx index 9b05da43..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,17 +288,228 @@ protected: const SGPropertyNode& _propertyNode; }; -HLAPropertyDataElement::HLAPropertyDataElement(HLAPropertyReference* propertyReference) : - _propertyReference(propertyReference) +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::HLAPropertyDataElement(const HLADataType* dataType, HLAPropertyReference* propertyReference) : - _dataType(dataType), - _propertyReference(propertyReference) +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() { } @@ -224,6 +525,11 @@ HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPr setPropertyNode(propertyNode); } +HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) : + _dataType(dataType) +{ +} + HLAPropertyDataElement::~HLAPropertyDataElement() { } @@ -231,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* @@ -267,41 +579,52 @@ 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) { - _propertyReference = new HLAPropertyReference; - _propertyReference->setRootNode(propertyNode); + _propertyNode = propertyNode; + if (_dataType.valid() && _propertyNode.valid()) + _dataElement = createDataElement(_dataType, _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(); +} + +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 51d1729b..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 @@ -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; @@ -102,11 +42,20 @@ 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 _propertyReference; + SGSharedPtr _dataElement; + SGSharedPtr _propertyNode; }; } // namespace simgear 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 \ 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; 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); } } } diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index e85d9659..01560b39 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 + sgio sgbucket sgstructure sgthreads sgtiming sgmisc sgdebug + ${CMAKE_THREAD_LIBS_INIT} + ${WINSOCK_LIBRARY} + ${ZLIB_LIBRARY} + ${RT_LIBRARY}) + \ No newline at end of file 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 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 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