Merge branch 'next' of git://gitorious.org/fg/simgear into next
This commit is contained in:
@@ -123,14 +123,14 @@ check_include_file(windows.h HAVE_WINDOWS_H)
|
||||
|
||||
if(ENABLE_RTI)
|
||||
# See if we have any rti library variant installed
|
||||
find_package(RTI)
|
||||
find_package(RTI)
|
||||
endif(ENABLE_RTI)
|
||||
|
||||
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
|
||||
check_function_exists(ftime HAVE_FTIME)
|
||||
check_function_exists(timegm HAVE_TIMEGM)
|
||||
check_function_exists(rint HAVE_RINT)
|
||||
|
||||
check_function_exists(mkdtemp HAVE_MKDTEMP)
|
||||
|
||||
if(HAVE_UNISTD_H)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_INCLUDE_PATH})
|
||||
|
||||
@@ -32,6 +32,7 @@ set(HLA_SOURCES
|
||||
HLABasicDataType.cxx
|
||||
HLADataElement.cxx
|
||||
HLADataType.cxx
|
||||
HLADataTypeVisitor.cxx
|
||||
HLAEnumeratedDataElement.cxx
|
||||
HLAEnumeratedDataType.cxx
|
||||
HLAFederate.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) :
|
||||
|
||||
@@ -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<const HLADataType> _elementDataType;
|
||||
bool _isOpaque;
|
||||
bool _isString;
|
||||
};
|
||||
|
||||
class HLAFixedArrayDataType : public HLAArrayDataType {
|
||||
|
||||
188
simgear/hla/HLADataTypeVisitor.cxx
Normal file
188
simgear/hla/HLADataTypeVisitor.cxx
Normal file
@@ -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<HLAArrayDataElement> 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<HLAArrayDataElement> 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<HLAFixedRecordDataElement> 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<HLAVariantDataElement> variantDataElement;
|
||||
variantDataElement = new HLAVariantDataElement(&dataType);
|
||||
variantDataElement->setDataElementFactory(new VariantDataElementFactory);
|
||||
_dataElement = variantDataElement;
|
||||
}
|
||||
|
||||
} // namespace simgear
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include "HLAArrayDataType.hxx"
|
||||
#include "HLABasicDataType.hxx"
|
||||
#include "HLADataTypeVisitor.hxx"
|
||||
#include "HLADataElement.hxx"
|
||||
#include "HLAEnumeratedDataType.hxx"
|
||||
#include "HLAFixedRecordDataType.hxx"
|
||||
#include "HLAVariantDataType.hxx"
|
||||
@@ -629,6 +629,43 @@ 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<HLADataElement> _dataElement;
|
||||
};
|
||||
|
||||
} // namespace simgear
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<HLADataElement>& getDataElement() const
|
||||
{ return _dataElement; }
|
||||
|
||||
private:
|
||||
SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
|
||||
{
|
||||
@@ -381,7 +378,6 @@ private:
|
||||
return dataElement;
|
||||
}
|
||||
|
||||
SGSharedPtr<HLADataElement> _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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,161 +17,251 @@
|
||||
|
||||
#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, HLAPropertyReference& propertyReference) :
|
||||
ScalarDecodeVisitor(HLADecodeStream& stream, SGPropertyNode& propertyNode) :
|
||||
HLADataTypeDecodeVisitor(stream),
|
||||
_propertyReference(propertyReference)
|
||||
_propertyNode(propertyNode)
|
||||
{ }
|
||||
virtual ~ScalarDecodeVisitor()
|
||||
{ }
|
||||
|
||||
virtual void apply(const HLAInt8DataType& dataType)
|
||||
{
|
||||
int8_t value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setIntValue(value);
|
||||
_propertyNode.setIntValue(value);
|
||||
}
|
||||
virtual void apply(const HLAUInt8DataType& dataType)
|
||||
{
|
||||
uint8_t value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setIntValue(value);
|
||||
_propertyNode.setIntValue(value);
|
||||
}
|
||||
virtual void apply(const HLAInt16DataType& dataType)
|
||||
{
|
||||
int16_t value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setIntValue(value);
|
||||
_propertyNode.setIntValue(value);
|
||||
}
|
||||
virtual void apply(const HLAUInt16DataType& dataType)
|
||||
{
|
||||
uint16_t value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setIntValue(value);
|
||||
_propertyNode.setIntValue(value);
|
||||
}
|
||||
virtual void apply(const HLAInt32DataType& dataType)
|
||||
{
|
||||
int32_t value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setIntValue(value);
|
||||
_propertyNode.setIntValue(value);
|
||||
}
|
||||
virtual void apply(const HLAUInt32DataType& dataType)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setIntValue(value);
|
||||
_propertyNode.setIntValue(value);
|
||||
}
|
||||
virtual void apply(const HLAInt64DataType& dataType)
|
||||
{
|
||||
int64_t value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setLongValue(value);
|
||||
_propertyNode.setLongValue(value);
|
||||
}
|
||||
virtual void apply(const HLAUInt64DataType& dataType)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setLongValue(value);
|
||||
_propertyNode.setLongValue(value);
|
||||
}
|
||||
virtual void apply(const HLAFloat32DataType& dataType)
|
||||
{
|
||||
float value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setFloatValue(value);
|
||||
_propertyNode.setFloatValue(value);
|
||||
}
|
||||
virtual void apply(const HLAFloat64DataType& dataType)
|
||||
{
|
||||
double value = 0;
|
||||
dataType.decode(_stream, value);
|
||||
_propertyReference.setDoubleValue(value);
|
||||
}
|
||||
|
||||
virtual void apply(const HLAFixedArrayDataType& dataType)
|
||||
{
|
||||
unsigned numElements = dataType.getNumElements();
|
||||
std::string value;
|
||||
value.reserve(numElements);
|
||||
for (unsigned i = 0; i < numElements; ++i) {
|
||||
HLATemplateDecodeVisitor<char> visitor(_stream);
|
||||
dataType.getElementDataType()->accept(visitor);
|
||||
value.push_back(visitor.getValue());
|
||||
}
|
||||
_propertyReference.setStringValue(value);
|
||||
}
|
||||
virtual void apply(const HLAVariableArrayDataType& dataType)
|
||||
{
|
||||
HLATemplateDecodeVisitor<unsigned> numElementsVisitor(_stream);
|
||||
dataType.getSizeDataType()->accept(numElementsVisitor);
|
||||
unsigned numElements = numElementsVisitor.getValue();
|
||||
std::string value;
|
||||
value.reserve(numElements);
|
||||
for (unsigned i = 0; i < numElements; ++i) {
|
||||
HLATemplateDecodeVisitor<char> visitor(_stream);
|
||||
dataType.getElementDataType()->accept(visitor);
|
||||
value.push_back(visitor.getValue());
|
||||
}
|
||||
_propertyReference.setStringValue(value);
|
||||
_propertyNode.setDoubleValue(value);
|
||||
}
|
||||
|
||||
protected:
|
||||
HLAPropertyReference& _propertyReference;
|
||||
SGPropertyNode& _propertyNode;
|
||||
};
|
||||
|
||||
class HLAPropertyDataElement::EncodeVisitor : public HLADataTypeEncodeVisitor {
|
||||
class HLAPropertyDataElement::ScalarEncodeVisitor : public HLADataTypeEncodeVisitor {
|
||||
public:
|
||||
EncodeVisitor(HLAEncodeStream& stream, const HLAPropertyReference& propertyReference) :
|
||||
ScalarEncodeVisitor(HLAEncodeStream& stream, const SGPropertyNode& propertyNode) :
|
||||
HLADataTypeEncodeVisitor(stream),
|
||||
_propertyReference(propertyReference)
|
||||
_propertyNode(propertyNode)
|
||||
{ }
|
||||
virtual ~ScalarEncodeVisitor()
|
||||
{ }
|
||||
|
||||
virtual void apply(const HLAInt8DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
||||
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||
}
|
||||
virtual void apply(const HLAUInt8DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
||||
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||
}
|
||||
virtual void apply(const HLAInt16DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
||||
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||
}
|
||||
virtual void apply(const HLAUInt16DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
||||
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||
}
|
||||
virtual void apply(const HLAInt32DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
||||
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||
}
|
||||
virtual void apply(const HLAUInt32DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getIntValue());
|
||||
dataType.encode(_stream, _propertyNode.getIntValue());
|
||||
}
|
||||
virtual void apply(const HLAInt64DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getLongValue());
|
||||
dataType.encode(_stream, _propertyNode.getLongValue());
|
||||
}
|
||||
virtual void apply(const HLAUInt64DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getLongValue());
|
||||
dataType.encode(_stream, _propertyNode.getLongValue());
|
||||
}
|
||||
virtual void apply(const HLAFloat32DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getFloatValue());
|
||||
dataType.encode(_stream, _propertyNode.getFloatValue());
|
||||
}
|
||||
virtual void apply(const HLAFloat64DataType& dataType)
|
||||
{
|
||||
dataType.encode(_stream, _propertyReference.getDoubleValue());
|
||||
dataType.encode(_stream, _propertyNode.getDoubleValue());
|
||||
}
|
||||
|
||||
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<const HLABasicDataType> _dataType;
|
||||
SGSharedPtr<SGPropertyNode> _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 = _propertyReference.getStringValue();
|
||||
std::string value;
|
||||
value.reserve(numElements);
|
||||
for (unsigned i = 0; i < numElements; ++i) {
|
||||
HLATemplateDecodeVisitor<char> visitor(_stream);
|
||||
dataType.getElementDataType()->accept(visitor);
|
||||
value.push_back(visitor.getValue());
|
||||
}
|
||||
_propertyNode.setStringValue(value);
|
||||
}
|
||||
virtual void apply(const HLAVariableArrayDataType& dataType)
|
||||
{
|
||||
HLATemplateDecodeVisitor<std::string::size_type> 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<char> 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();
|
||||
std::string value = _propertyNode.getStringValue();
|
||||
for (unsigned i = 0; i < numElements; ++i) {
|
||||
if (i < value.size()) {
|
||||
HLATemplateEncodeVisitor<char> visitor(_stream, value[i]);
|
||||
@@ -185,7 +275,7 @@ public:
|
||||
|
||||
virtual void apply(const HLAVariableArrayDataType& dataType)
|
||||
{
|
||||
std::string value = _propertyReference.getStringValue();
|
||||
std::string value = _propertyNode.getStringValue();
|
||||
HLATemplateEncodeVisitor<std::string::size_type> numElementsVisitor(_stream, value.size());
|
||||
dataType.getSizeDataType()->accept(numElementsVisitor);
|
||||
for (unsigned i = 0; i < value.size(); ++i) {
|
||||
@@ -195,17 +285,248 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
const HLAPropertyReference& _propertyReference;
|
||||
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<const HLAArrayDataType> _dataType;
|
||||
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||
};
|
||||
|
||||
HLAPropertyDataElement::StringDataElement::StringDataElement(const HLAArrayDataType* dataType, SGPropertyNode* propertyNode) :
|
||||
_dataType(dataType),
|
||||
_propertyNode(propertyNode)
|
||||
{
|
||||
}
|
||||
|
||||
HLAPropertyDataElement::HLAPropertyDataElement(const simgear::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<SGPropertyNode> _propertyNode;
|
||||
};
|
||||
|
||||
virtual void apply(const HLAFixedArrayDataType& dataType)
|
||||
{
|
||||
if (dataType.getIsString()) {
|
||||
_dataElement = new StringDataElement(&dataType, _propertyNode.get());
|
||||
} else {
|
||||
SGSharedPtr<HLAArrayDataElement> arrayDataElement;
|
||||
arrayDataElement = new HLAArrayDataElement(&dataType);
|
||||
arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
|
||||
arrayDataElement->setNumElements(dataType.getNumElements());
|
||||
_dataElement = arrayDataElement;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void apply(const HLAVariableArrayDataType& dataType)
|
||||
{
|
||||
if (dataType.getIsString()) {
|
||||
_dataElement = new StringDataElement(&dataType, _propertyNode.get());
|
||||
} else {
|
||||
SGSharedPtr<HLAArrayDataElement> arrayDataElement;
|
||||
arrayDataElement = new HLAArrayDataElement(&dataType);
|
||||
arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_propertyNode.get()));
|
||||
_dataElement = arrayDataElement;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void apply(const HLAEnumeratedDataType& dataType)
|
||||
{
|
||||
_dataElement = new ScalarDataElement(dataType.getRepresentation(), _propertyNode.get());
|
||||
}
|
||||
|
||||
virtual void apply(const HLAFixedRecordDataType& dataType)
|
||||
{
|
||||
SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
|
||||
recordDataElement = new HLAFixedRecordDataElement(&dataType);
|
||||
|
||||
unsigned numFields = dataType.getNumFields();
|
||||
for (unsigned i = 0; i < numFields; ++i) {
|
||||
DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType.getFieldName(i), 0, true));
|
||||
dataType.getFieldDataType(i)->accept(visitor);
|
||||
recordDataElement->setField(i, visitor._dataElement.get());
|
||||
}
|
||||
|
||||
_dataElement = recordDataElement;
|
||||
}
|
||||
|
||||
class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory {
|
||||
public:
|
||||
VariantDataElementFactory(SGPropertyNode* propertyNode) :
|
||||
_propertyNode(propertyNode)
|
||||
{ }
|
||||
virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index)
|
||||
{
|
||||
const HLAVariantDataType* dataType = element.getDataType();
|
||||
if (!dataType)
|
||||
return 0;
|
||||
const HLADataType* alternativeDataType = element.getAlternativeDataType();
|
||||
if (!alternativeDataType)
|
||||
return 0;
|
||||
DataElementFactoryVisitor visitor(_propertyNode->getChild(dataType->getAlternativeName(index), 0, true));
|
||||
alternativeDataType->accept(visitor);
|
||||
return visitor.getDataElement();
|
||||
}
|
||||
private:
|
||||
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||
};
|
||||
|
||||
virtual void apply(const HLAVariantDataType& dataType)
|
||||
{
|
||||
SGSharedPtr<HLAVariantDataElement> variantDataElement;
|
||||
variantDataElement = new HLAVariantDataElement(&dataType);
|
||||
variantDataElement->setDataElementFactory(new VariantDataElementFactory(_propertyNode.get()));
|
||||
_dataElement = variantDataElement;
|
||||
}
|
||||
|
||||
HLADataElement* getDataElement()
|
||||
{ return _dataElement.release(); }
|
||||
|
||||
private:
|
||||
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||
SGSharedPtr<HLADataElement> _dataElement;
|
||||
};
|
||||
|
||||
HLAPropertyDataElement::HLAPropertyDataElement()
|
||||
{
|
||||
}
|
||||
|
||||
HLAPropertyDataElement::HLAPropertyDataElement(SGPropertyNode* propertyNode)
|
||||
{
|
||||
setPropertyNode(propertyNode);
|
||||
}
|
||||
|
||||
HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode) :
|
||||
_dataType(dataType)
|
||||
{
|
||||
setPropertyNode(propertyNode);
|
||||
}
|
||||
|
||||
HLAPropertyDataElement::HLAPropertyDataElement(const HLADataType* dataType) :
|
||||
_dataType(dataType)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -216,31 +537,37 @@ HLAPropertyDataElement::~HLAPropertyDataElement()
|
||||
bool
|
||||
HLAPropertyDataElement::encode(HLAEncodeStream& stream) const
|
||||
{
|
||||
if (!_dataType.valid())
|
||||
return false;
|
||||
if (_propertyReference.valid()) {
|
||||
EncodeVisitor visitor(stream, *_propertyReference);
|
||||
_dataType->accept(visitor);
|
||||
if (_dataElement.valid()) {
|
||||
return _dataElement->encode(stream);
|
||||
} else {
|
||||
if (!_dataType.valid())
|
||||
return false;
|
||||
HLADataTypeEncodeVisitor visitor(stream);
|
||||
_dataType->accept(visitor);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HLAPropertyDataElement::decode(HLADecodeStream& stream)
|
||||
{
|
||||
if (!_dataType.valid())
|
||||
if (_dataElement.valid()) {
|
||||
return _dataElement->decode(stream);
|
||||
} else if (!_dataType.valid()) {
|
||||
// We cant do anything if the data type is not valid
|
||||
return false;
|
||||
if (_propertyReference.valid()) {
|
||||
DecodeVisitor visitor(stream, *_propertyReference);
|
||||
_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*
|
||||
@@ -252,18 +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;
|
||||
_dataType = dataType;
|
||||
if (_dataType.valid() && _propertyNode.valid())
|
||||
_dataElement = createDataElement(_dataType, _propertyNode);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HLAPropertyDataElement::setPropertyNode(SGPropertyNode* propertyNode)
|
||||
{
|
||||
_propertyNode = propertyNode;
|
||||
if (_dataType.valid() && _propertyNode.valid())
|
||||
_dataElement = createDataElement(_dataType, _propertyNode);
|
||||
}
|
||||
|
||||
SGPropertyNode*
|
||||
HLAPropertyDataElement::getPropertyNode()
|
||||
{
|
||||
return _propertyNode.get();
|
||||
}
|
||||
|
||||
const SGPropertyNode*
|
||||
HLAPropertyDataElement::getPropertyNode() const
|
||||
{
|
||||
return _propertyNode.get();
|
||||
}
|
||||
|
||||
HLADataElement*
|
||||
HLAPropertyDataElement::createDataElement(const SGSharedPtr<const HLADataType>& dataType,
|
||||
const SGSharedPtr<SGPropertyNode>& propertyNode)
|
||||
{
|
||||
DataElementFactoryVisitor visitor(propertyNode);
|
||||
dataType->accept(visitor);
|
||||
SGSharedPtr<HLADataElement> dataElement = visitor.getDataElement();
|
||||
|
||||
// Copy over the content of the previous data element if there is any.
|
||||
if (_dataElement.valid()) {
|
||||
// FIXME is encode/decode the right tool here??
|
||||
RTIData data;
|
||||
HLAEncodeStream encodeStream(data);
|
||||
if (_dataElement->encode(encodeStream)) {
|
||||
HLADecodeStream decodeStream(data);
|
||||
dataElement->decode(decodeStream);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return dataElement.release();
|
||||
}
|
||||
|
||||
} // namespace simgear
|
||||
|
||||
@@ -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,139 +18,17 @@
|
||||
#ifndef HLAPropertyDataElement_hxx
|
||||
#define HLAPropertyDataElement_hxx
|
||||
|
||||
#include <set>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include "HLADataElement.hxx"
|
||||
|
||||
namespace simgear {
|
||||
|
||||
class HLAPropertyReference : public SGReferenced {
|
||||
public:
|
||||
HLAPropertyReference()
|
||||
{ }
|
||||
HLAPropertyReference(const std::string& relativePath) :
|
||||
_relativePath(relativePath)
|
||||
{ }
|
||||
|
||||
void setIntValue(int value)
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return;
|
||||
_propertyNode->setIntValue(value);
|
||||
}
|
||||
int getIntValue() const
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return 0;
|
||||
return _propertyNode->getIntValue();
|
||||
}
|
||||
|
||||
void setLongValue(long value)
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return;
|
||||
_propertyNode->setLongValue(value);
|
||||
}
|
||||
long getLongValue() const
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return 0;
|
||||
return _propertyNode->getLongValue();
|
||||
}
|
||||
|
||||
void setFloatValue(float value)
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return;
|
||||
_propertyNode->setFloatValue(value);
|
||||
}
|
||||
float getFloatValue() const
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return 0;
|
||||
return _propertyNode->getFloatValue();
|
||||
}
|
||||
|
||||
void setDoubleValue(double value)
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return;
|
||||
_propertyNode->setDoubleValue(value);
|
||||
}
|
||||
double getDoubleValue() const
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return 0;
|
||||
return _propertyNode->getDoubleValue();
|
||||
}
|
||||
|
||||
void setStringValue(const std::string& value)
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return;
|
||||
_propertyNode->setStringValue(value);
|
||||
}
|
||||
std::string getStringValue() const
|
||||
{
|
||||
if (!_propertyNode.valid())
|
||||
return std::string();
|
||||
return _propertyNode->getStringValue();
|
||||
}
|
||||
|
||||
SGPropertyNode* getPropertyNode()
|
||||
{ return _propertyNode.get(); }
|
||||
|
||||
void setRootNode(SGPropertyNode* rootNode)
|
||||
{
|
||||
if (!rootNode)
|
||||
_propertyNode.clear();
|
||||
else
|
||||
_propertyNode = rootNode->getNode(_relativePath, true);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _relativePath;
|
||||
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||
};
|
||||
|
||||
class HLAPropertyReferenceSet : public SGReferenced {
|
||||
public:
|
||||
void insert(const SGSharedPtr<HLAPropertyReference>& propertyReference)
|
||||
{
|
||||
_propertyReferenceSet.insert(propertyReference);
|
||||
propertyReference->setRootNode(_rootNode.get());
|
||||
}
|
||||
void remove(const SGSharedPtr<HLAPropertyReference>& propertyReference)
|
||||
{
|
||||
PropertyReferenceSet::iterator i = _propertyReferenceSet.find(propertyReference);
|
||||
if (i == _propertyReferenceSet.end())
|
||||
return;
|
||||
_propertyReferenceSet.erase(i);
|
||||
propertyReference->setRootNode(0);
|
||||
}
|
||||
|
||||
void setRootNode(SGPropertyNode* rootNode)
|
||||
{
|
||||
_rootNode = rootNode;
|
||||
for (PropertyReferenceSet::iterator i = _propertyReferenceSet.begin();
|
||||
i != _propertyReferenceSet.end(); ++i) {
|
||||
(*i)->setRootNode(_rootNode.get());
|
||||
}
|
||||
}
|
||||
SGPropertyNode* getRootNode()
|
||||
{ return _rootNode.get(); }
|
||||
|
||||
private:
|
||||
SGSharedPtr<SGPropertyNode> _rootNode;
|
||||
|
||||
typedef std::set<SGSharedPtr<HLAPropertyReference> > PropertyReferenceSet;
|
||||
PropertyReferenceSet _propertyReferenceSet;
|
||||
};
|
||||
|
||||
class HLAPropertyDataElement : public HLADataElement {
|
||||
public:
|
||||
HLAPropertyDataElement(HLAPropertyReference* propertyReference);
|
||||
HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference);
|
||||
HLAPropertyDataElement();
|
||||
HLAPropertyDataElement(SGPropertyNode* propertyNode);
|
||||
HLAPropertyDataElement(const HLADataType* dataType, SGPropertyNode* propertyNode);
|
||||
HLAPropertyDataElement(const HLADataType* dataType);
|
||||
virtual ~HLAPropertyDataElement();
|
||||
|
||||
virtual bool encode(HLAEncodeStream& stream) const;
|
||||
@@ -159,12 +37,25 @@ public:
|
||||
virtual const HLADataType* getDataType() const;
|
||||
virtual bool setDataType(const HLADataType* dataType);
|
||||
|
||||
void setPropertyNode(SGPropertyNode* propertyNode);
|
||||
SGPropertyNode* getPropertyNode();
|
||||
const SGPropertyNode* getPropertyNode() const;
|
||||
|
||||
private:
|
||||
class DecodeVisitor;
|
||||
class EncodeVisitor;
|
||||
HLADataElement*
|
||||
createDataElement(const SGSharedPtr<const HLADataType>& dataType, const SGSharedPtr<SGPropertyNode>& propertyNode);
|
||||
|
||||
class ScalarDecodeVisitor;
|
||||
class ScalarEncodeVisitor;
|
||||
class ScalarDataElement;
|
||||
class StringDecodeVisitor;
|
||||
class StringEncodeVisitor;
|
||||
class StringDataElement;
|
||||
class DataElementFactoryVisitor;
|
||||
|
||||
SGSharedPtr<const HLADataType> _dataType;
|
||||
SGSharedPtr<HLAPropertyReference> _propertyReference;
|
||||
SGSharedPtr<HLADataElement> _dataElement;
|
||||
SGSharedPtr<SGPropertyNode> _propertyNode;
|
||||
};
|
||||
|
||||
} // namespace simgear
|
||||
|
||||
@@ -35,6 +35,7 @@ libsghla_a_SOURCES = \
|
||||
HLABasicDataType.cxx \
|
||||
HLADataElement.cxx \
|
||||
HLADataType.cxx \
|
||||
HLADataTypeVisitor.cxx \
|
||||
HLAEnumeratedDataElement.cxx \
|
||||
HLAEnumeratedDataType.cxx \
|
||||
HLAFederate.cxx \
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -177,47 +177,56 @@ RTI13ObjectInstance::localDeleteObjectInstance()
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag)
|
||||
RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag)
|
||||
{
|
||||
// Retrieve an empty update struct from the memory pool
|
||||
UpdateList updateList;
|
||||
getUpdateFromPool(updateList);
|
||||
|
||||
RTI::ULong numAttribs = attributeValuePairSet.size();
|
||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||
unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i));
|
||||
RTIIndexDataPairList indexDataPairList;
|
||||
for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
|
||||
i != attributeHandleDataPairList.end(); ++i) {
|
||||
unsigned index = getAttributeIndex(i->first);
|
||||
// Get a RTIData from the data pool
|
||||
getDataFromPool(index, updateList.back()._indexDataPairList);
|
||||
RTI::ULong length = attributeValuePairSet.getValueLength(i);
|
||||
updateList.back()._indexDataPairList.back().second.resize(length);
|
||||
attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length);
|
||||
updateList.back()._tag = tag;
|
||||
getDataFromPool(indexDataPairList);
|
||||
indexDataPairList.back().first = index;
|
||||
indexDataPairList.back().second.swap(i->second);
|
||||
}
|
||||
|
||||
RTIObjectInstance::reflectAttributeValues(indexDataPairList, tag);
|
||||
|
||||
RTIIndexDataPairList::iterator j = indexDataPairList.begin();
|
||||
for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
|
||||
i != attributeHandleDataPairList.end(); ++i, ++j) {
|
||||
i->second.swap(j->second);
|
||||
}
|
||||
|
||||
RTIObjectInstance::reflectAttributeValues(updateList.front()._indexDataPairList, tag);
|
||||
// Return the update data back to the pool
|
||||
putUpdateToPool(updateList);
|
||||
putDataToPool(indexDataPairList);
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag)
|
||||
RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList,
|
||||
const SGTimeStamp& timeStamp, const RTIData& tag)
|
||||
{
|
||||
// Retrieve an empty update struct from the memory pool
|
||||
UpdateList updateList;
|
||||
getUpdateFromPool(updateList);
|
||||
|
||||
RTI::ULong numAttribs = attributeValuePairSet.size();
|
||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||
unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i));
|
||||
RTIIndexDataPairList indexDataPairList;
|
||||
for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
|
||||
i != attributeHandleDataPairList.end(); ++i) {
|
||||
unsigned index = getAttributeIndex(i->first);
|
||||
// Get a RTIData from the data pool
|
||||
getDataFromPool(index, updateList.back()._indexDataPairList);
|
||||
RTI::ULong length = attributeValuePairSet.getValueLength(i);
|
||||
updateList.back()._indexDataPairList.back().second.resize(length);
|
||||
attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length);
|
||||
updateList.back()._tag = tag;
|
||||
getDataFromPool(indexDataPairList);
|
||||
indexDataPairList.back().first = index;
|
||||
indexDataPairList.back().second.swap(i->second);
|
||||
}
|
||||
|
||||
scheduleUpdates(timeStamp, updateList);
|
||||
RTIObjectInstance::reflectAttributeValues(indexDataPairList, timeStamp, tag);
|
||||
|
||||
RTIIndexDataPairList::iterator j = indexDataPairList.begin();
|
||||
for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin();
|
||||
i != attributeHandleDataPairList.end(); ++i, ++j) {
|
||||
i->second.swap(j->second);
|
||||
}
|
||||
|
||||
// Return the update data back to the pool
|
||||
putDataToPool(indexDataPairList);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -273,12 +282,12 @@ RTI13ObjectInstance::requestObjectAttributeValueUpdate()
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes)
|
||||
RTI13ObjectInstance::provideAttributeValueUpdate(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||
{
|
||||
// Called from the ambassador. Just marks some instance attributes dirty so that they are sent with the next update
|
||||
RTI::ULong numAttribs = attributes.size();
|
||||
size_t numAttribs = attributeHandleSet.size();
|
||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||
unsigned index = getAttributeIndex(attributes.getHandle(i));
|
||||
unsigned index = getAttributeIndex(attributeHandleSet[i]);
|
||||
setAttributeForceUpdate(index);
|
||||
}
|
||||
}
|
||||
@@ -400,72 +409,72 @@ RTI13ObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const R
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::attributesInScope(const RTI::AttributeHandleSet& attributeHandleSet)
|
||||
RTI13ObjectInstance::attributesInScope(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||
{
|
||||
RTI::ULong numAttribs = attributeHandleSet.size();
|
||||
size_t numAttribs = attributeHandleSet.size();
|
||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||
RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
|
||||
RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
|
||||
setAttributeInScope(getAttributeIndex(attributeHandle), true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::attributesOutOfScope(const RTI::AttributeHandleSet& attributeHandleSet)
|
||||
RTI13ObjectInstance::attributesOutOfScope(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||
{
|
||||
RTI::ULong numAttribs = attributeHandleSet.size();
|
||||
size_t numAttribs = attributeHandleSet.size();
|
||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||
RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
|
||||
RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
|
||||
setAttributeInScope(getAttributeIndex(attributeHandle), false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet)
|
||||
RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||
{
|
||||
RTI::ULong numAttribs = attributeHandleSet.size();
|
||||
size_t numAttribs = attributeHandleSet.size();
|
||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||
RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
|
||||
RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
|
||||
setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet)
|
||||
RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const std::vector<RTI::AttributeHandle>& attributeHandleSet)
|
||||
{
|
||||
RTI::ULong numAttribs = attributeHandleSet.size();
|
||||
size_t numAttribs = attributeHandleSet.size();
|
||||
for (RTI::ULong i = 0; i < numAttribs; ++i) {
|
||||
RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i);
|
||||
RTI::AttributeHandle attributeHandle = attributeHandleSet[i];
|
||||
setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag)
|
||||
RTI13ObjectInstance::requestAttributeOwnershipAssumption(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes)
|
||||
RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const std::vector<RTI::AttributeHandle>& attributes)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes)
|
||||
RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const std::vector<RTI::AttributeHandle>& attributes)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes)
|
||||
RTI13ObjectInstance::attributeOwnershipUnavailable(const std::vector<RTI::AttributeHandle>& attributes)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag)
|
||||
RTI13ObjectInstance::requestAttributeOwnershipRelease(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes)
|
||||
RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const std::vector<RTI::AttributeHandle>& attributes)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ namespace simgear {
|
||||
class RTI13Ambassador;
|
||||
class RTI13ObjectClass;
|
||||
|
||||
typedef std::pair<RTI::AttributeHandle, RTIData> RTI13AttributeHandleDataPair;
|
||||
typedef std::list<RTI13AttributeHandleDataPair> RTI13AttributeHandleDataPairList;
|
||||
|
||||
class RTI13ObjectInstance : public RTIObjectInstance {
|
||||
public:
|
||||
RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned);
|
||||
@@ -65,27 +68,27 @@ public:
|
||||
virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||
virtual void localDeleteObjectInstance();
|
||||
|
||||
void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag);
|
||||
void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||
void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag);
|
||||
void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||
virtual void requestObjectAttributeValueUpdate();
|
||||
void provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes);
|
||||
void provideAttributeValueUpdate(const std::vector<RTI::AttributeHandle>& attributes);
|
||||
|
||||
virtual void updateAttributeValues(const RTIData& tag);
|
||||
virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||
|
||||
void attributesInScope(const RTI::AttributeHandleSet& attributes);
|
||||
void attributesOutOfScope(const RTI::AttributeHandleSet& attributes);
|
||||
void attributesInScope(const std::vector<RTI::AttributeHandle>& attributes);
|
||||
void attributesOutOfScope(const std::vector<RTI::AttributeHandle>& attributes);
|
||||
|
||||
void turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributes);
|
||||
void turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributes);
|
||||
void turnUpdatesOnForObjectInstance(const std::vector<RTI::AttributeHandle>& attributes);
|
||||
void turnUpdatesOffForObjectInstance(const std::vector<RTI::AttributeHandle>& attributes);
|
||||
|
||||
// Not yet sure what to do here. But the dispatch functions are already there
|
||||
void requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag);
|
||||
void attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes);
|
||||
void attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes);
|
||||
void attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes);
|
||||
void requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag);
|
||||
void confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes);
|
||||
void requestAttributeOwnershipAssumption(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag);
|
||||
void attributeOwnershipDivestitureNotification(const std::vector<RTI::AttributeHandle>& attributes);
|
||||
void attributeOwnershipAcquisitionNotification(const std::vector<RTI::AttributeHandle>& attributes);
|
||||
void attributeOwnershipUnavailable(const std::vector<RTI::AttributeHandle>& attributes);
|
||||
void requestAttributeOwnershipRelease(const std::vector<RTI::AttributeHandle>& attributes, const RTIData& tag);
|
||||
void confirmAttributeOwnershipAcquisitionCancellation(const std::vector<RTI::AttributeHandle>& attributes);
|
||||
void informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle);
|
||||
void attributeIsNotOwned(RTI::AttributeHandle attributeHandle);
|
||||
void attributeOwnedByRTI(RTI::AttributeHandle attributeHandle);
|
||||
|
||||
@@ -115,6 +115,13 @@ public:
|
||||
ensureCapacity(capacity);
|
||||
}
|
||||
|
||||
void swap(RTIData& data)
|
||||
{
|
||||
std::swap(_data, data._data);
|
||||
std::swap(_size, data._size);
|
||||
std::swap(_capacity, data._capacity);
|
||||
}
|
||||
|
||||
void setData(char* data, unsigned size)
|
||||
{
|
||||
if (_capacity)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -39,6 +39,7 @@ RTIObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIDat
|
||||
return;
|
||||
}
|
||||
hlaObjectClass->discoverInstance(objectInstance, tag);
|
||||
objectInstance->requestObjectAttributeValueUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -60,20 +60,6 @@ public:
|
||||
virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) = 0;
|
||||
|
||||
void removeInstance(const RTIData& tag);
|
||||
// Call this if you want to roll up the queued timestamed updates
|
||||
// and reflect that into the attached data elements.
|
||||
void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
|
||||
{
|
||||
// replay all updates up to the given timestamp
|
||||
UpdateListMap::iterator last = _updateListMap.upper_bound(timeStamp);
|
||||
for (UpdateListMap::iterator i = _updateListMap.begin(); i != last; ++i) {
|
||||
for (UpdateList::iterator j = i->second.begin(); j != i->second.end(); ++j) {
|
||||
// FIXME have a variant that takes the timestamp?
|
||||
reflectAttributeValues(j->_indexDataPairList, j->_tag);
|
||||
}
|
||||
putUpdateToPool(i->second);
|
||||
}
|
||||
}
|
||||
void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag);
|
||||
void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag);
|
||||
void reflectAttributeValue(unsigned i, const RTIData& data)
|
||||
@@ -133,6 +119,8 @@ public:
|
||||
} else {
|
||||
_attributeData[i].setUpdateEnabled(false);
|
||||
_attributeData[i].setOwned(false);
|
||||
if (getAttributeSubscribed(i))
|
||||
_attributeData[i].setRequestUpdate(true);
|
||||
}
|
||||
}
|
||||
_attributeData.resize(numAttributes);
|
||||
@@ -140,9 +128,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,80 +227,25 @@ protected:
|
||||
// Is true if we should emit a requestattr
|
||||
bool _pendingAttributeUpdateRequest;
|
||||
|
||||
// Contains a full update as it came in from the RTI
|
||||
struct Update {
|
||||
RTIIndexDataPairList _indexDataPairList;
|
||||
RTIData _tag;
|
||||
};
|
||||
// A bunch of updates for the same timestamp
|
||||
typedef std::list<Update> UpdateList;
|
||||
// The timestamp sorted list of updates
|
||||
typedef std::map<SGTimeStamp, UpdateList> UpdateListMap;
|
||||
|
||||
// The timestamped updates sorted by timestamp
|
||||
UpdateListMap _updateListMap;
|
||||
|
||||
// The pool of unused updates so that we do not need to malloc/free each time
|
||||
UpdateList _updateList;
|
||||
|
||||
void getUpdateFromPool(UpdateList& updateList)
|
||||
{
|
||||
if (_updateList.empty())
|
||||
updateList.push_back(Update());
|
||||
else
|
||||
updateList.splice(updateList.end(), _updateList, _updateList.begin());
|
||||
}
|
||||
void putUpdateToPool(UpdateList& updateList)
|
||||
{
|
||||
for (UpdateList::iterator i = updateList.begin(); i != updateList.end(); ++i)
|
||||
putDataToPool(i->_indexDataPairList);
|
||||
_updateList.splice(_updateList.end(), updateList);
|
||||
}
|
||||
|
||||
// Appends the updates in the list to the given timestamps updates
|
||||
void scheduleUpdates(const SGTimeStamp& timeStamp, UpdateList& updateList)
|
||||
{
|
||||
UpdateListMap::iterator i = _updateListMap.find(timeStamp);
|
||||
if (i == _updateListMap.end())
|
||||
i = _updateListMap.insert(UpdateListMap::value_type(timeStamp, UpdateList())).first;
|
||||
i->second.splice(i->second.end(), updateList);
|
||||
}
|
||||
// Pool of update list entries
|
||||
RTIIndexDataPairList _indexDataPairList;
|
||||
|
||||
// This adds raw storage for attribute index i to the end of the dataPairList.
|
||||
void getDataFromPool(unsigned i, RTIIndexDataPairList& dataPairList)
|
||||
void getDataFromPool(RTIIndexDataPairList& dataPairList)
|
||||
{
|
||||
if (_attributeData.size() <= i) {
|
||||
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing left in the pool - so allocate something
|
||||
if (_attributeData[i]._indexDataPairList.empty()) {
|
||||
if (_indexDataPairList.empty()) {
|
||||
dataPairList.push_back(RTIIndexDataPairList::value_type());
|
||||
dataPairList.back().first = i;
|
||||
return;
|
||||
}
|
||||
|
||||
// Take one from the pool
|
||||
dataPairList.splice(dataPairList.end(),
|
||||
_attributeData[i]._indexDataPairList,
|
||||
_attributeData[i]._indexDataPairList.begin());
|
||||
dataPairList.splice(dataPairList.end(), _indexDataPairList, _indexDataPairList.begin());
|
||||
}
|
||||
|
||||
void putDataToPool(RTIIndexDataPairList& dataPairList)
|
||||
{
|
||||
while (!dataPairList.empty()) {
|
||||
// Put back into the pool
|
||||
unsigned i = dataPairList.front().first;
|
||||
if (_attributeData.size() <= i) {
|
||||
// should not happen!!!
|
||||
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
|
||||
dataPairList.pop_front();
|
||||
} else {
|
||||
_attributeData[i]._indexDataPairList.splice(_attributeData[i]._indexDataPairList.begin(),
|
||||
dataPairList, dataPairList.begin());
|
||||
}
|
||||
}
|
||||
_indexDataPairList.splice(_indexDataPairList.begin(), dataPairList);
|
||||
}
|
||||
|
||||
struct AttributeData {
|
||||
|
||||
@@ -57,3 +57,22 @@ 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})
|
||||
|
||||
add_executable(test_binobj test_binobj.cxx)
|
||||
target_link_libraries(test_binobj
|
||||
sgio sgbucket sgstructure sgthreads sgtiming sgmisc sgdebug
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${WINSOCK_LIBRARY}
|
||||
${ZLIB_LIBRARY}
|
||||
${RT_LIBRARY})
|
||||
|
||||
add_test(binobj ${EXECUTABLE_OUTPUT_PATH}/test_binobj)
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#include "sg_binobj.hxx"
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,29 +27,24 @@
|
||||
#ifndef _SG_BINOBJ_HXX
|
||||
#define _SG_BINOBJ_HXX
|
||||
|
||||
#include <zlib.h> // for gzFile
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/bucket/newbucket.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
/** STL Structure used to store object information */
|
||||
typedef std::vector < int_list > group_list;
|
||||
typedef group_list::iterator group_list_iterator;
|
||||
typedef group_list::const_iterator const_group_list_iterator;
|
||||
|
||||
|
||||
/** Magic Number for our file format */
|
||||
#define SG_FILE_MAGIC_NUMBER ( ('S'<<24) + ('G'<<16) + SG_BINOBJ_VERSION )
|
||||
|
||||
// forward decls
|
||||
class SGBucket;
|
||||
class SGPath;
|
||||
|
||||
/**
|
||||
* A class to manipulate the simgear 3d object format.
|
||||
@@ -85,6 +80,7 @@ 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
|
||||
|
||||
261
simgear/io/test_binobj.cxx
Normal file
261
simgear/io/test_binobj.cxx
Normal file
@@ -0,0 +1,261 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define random rand
|
||||
#endif
|
||||
|
||||
#include <simgear/misc/sg_dir.hxx>
|
||||
|
||||
#include "sg_binobj.hxx"
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
|
||||
#define COMPARE(a, b) \
|
||||
if ((a) != (b)) { \
|
||||
cerr << "failed:" << #a << " != " << #b << endl; \
|
||||
cerr << "\tgot:" << a << endl; \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define VERIFY(a) \
|
||||
if (!(a)) { \
|
||||
cerr << "failed:" << #a << endl; \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
void generate_points(int count, std::vector<SGVec3d>& vec)
|
||||
{
|
||||
for (int i=0; i<count; ++i) {
|
||||
vec.push_back(SGVec3d(i * 0.5, i * i, i * 4));
|
||||
}
|
||||
}
|
||||
|
||||
void generate_normals(int count, std::vector<SGVec3f>& vec)
|
||||
{
|
||||
for (int i=0; i<count; ++i) {
|
||||
vec.push_back(normalize(SGVec3f(i, i * 2, i * -4)));
|
||||
}
|
||||
}
|
||||
|
||||
void generate_tcs(int count, std::vector<SGVec2f>& vec)
|
||||
{
|
||||
for (int i=0; i<count; ++i) {
|
||||
vec.push_back(SGVec2f(1.0 / i, 16.0 / i));
|
||||
}
|
||||
}
|
||||
|
||||
void test_empty()
|
||||
{
|
||||
SGBinObject empty;
|
||||
SGPath path(simgear::Dir::current().file("empty.btg.gz"));
|
||||
bool ok = empty.write_bin_file(path);
|
||||
VERIFY( ok );
|
||||
SGBinObject rd;
|
||||
ok = rd.read_bin(path.str()) ;
|
||||
VERIFY( ok);
|
||||
|
||||
COMPARE(rd.get_wgs84_nodes().size(), 0);
|
||||
VERIFY(rd.get_pt_materials().empty());
|
||||
}
|
||||
|
||||
void comparePoints(const SGBinObject& rd, const std::vector<SGVec3d>& b)
|
||||
{
|
||||
for (unsigned int i=1; i<b.size(); i += 10) {
|
||||
SGVec3d pos = rd.get_wgs84_nodes()[i];
|
||||
pos += rd.get_gbs_center();
|
||||
|
||||
if (!equivalent(pos, b[i], 0.1)) {
|
||||
cout << "i=" << i << endl;
|
||||
cout << b[i] << endl;
|
||||
cout << pos << endl;
|
||||
}
|
||||
|
||||
VERIFY(equivalent(pos, b[i], 0.1));
|
||||
}
|
||||
}
|
||||
|
||||
void compareTexCoords(const SGBinObject& rd, const std::vector<SGVec2f>& b)
|
||||
{
|
||||
for (unsigned int i=1; i<b.size(); i += 10) {
|
||||
SGVec2f pos = rd.get_texcoords()[i];
|
||||
VERIFY(equivalent(pos, b[i], 0.001f));
|
||||
}
|
||||
}
|
||||
|
||||
int_list make_tri(int maxIndex)
|
||||
{
|
||||
int_list r;
|
||||
r.push_back(random() % maxIndex);
|
||||
r.push_back(random() % maxIndex);
|
||||
r.push_back(random() % maxIndex);
|
||||
return r;
|
||||
}
|
||||
|
||||
void compareTris(const SGBinObject& a, const SGBinObject& b)
|
||||
{
|
||||
unsigned int count = a.get_tri_materials().size();
|
||||
for (unsigned int i=0; i<count; i += 39) {
|
||||
const int_list& vA(a.get_tris_v()[i]);
|
||||
const int_list& vB(b.get_tris_v()[i]);
|
||||
VERIFY(vA == vB);
|
||||
|
||||
COMPARE(a.get_tri_materials()[i], b.get_tri_materials()[i]);
|
||||
|
||||
const int_list& tA(a.get_tris_tc()[i]);
|
||||
const int_list& tB(b.get_tris_tc()[i]);
|
||||
VERIFY(tA == tB);
|
||||
}
|
||||
}
|
||||
|
||||
void generate_tris(SGBinObject& b, int count)
|
||||
{
|
||||
group_list v, n, tc;
|
||||
string_list materials;
|
||||
|
||||
int maxVertices = b.get_wgs84_nodes().size();
|
||||
int maxNormals = b.get_normals().size();
|
||||
int maxTCs = b.get_texcoords().size();
|
||||
|
||||
for (int t=0; t<count; ++t) {
|
||||
v.push_back(make_tri(maxVertices));
|
||||
n.push_back(make_tri(maxNormals));
|
||||
tc.push_back(make_tri(maxTCs));
|
||||
materials.push_back("material1");
|
||||
}
|
||||
|
||||
b.set_tris_v(v);
|
||||
b.set_tris_n(n);
|
||||
b.set_tris_tc(tc);
|
||||
b.set_tri_materials(materials);
|
||||
}
|
||||
|
||||
void test_basic()
|
||||
{
|
||||
SGBinObject basic;
|
||||
SGPath path(simgear::Dir::current().file("basic.btg.gz"));
|
||||
|
||||
SGVec3d center(1, 2, 3);
|
||||
basic.set_gbs_center(center);
|
||||
basic.set_gbs_radius(12345);
|
||||
|
||||
std::vector<SGVec3d> points;
|
||||
generate_points(1024, points);
|
||||
std::vector<SGVec3f> normals;
|
||||
generate_normals(1024, normals);
|
||||
std::vector<SGVec2f> texCoords;
|
||||
generate_tcs(10000, texCoords);
|
||||
|
||||
basic.set_wgs84_nodes(points);
|
||||
basic.set_normals(normals);
|
||||
basic.set_texcoords(texCoords);
|
||||
|
||||
bool ok = basic.write_bin_file(path);
|
||||
VERIFY( ok );
|
||||
|
||||
SGBinObject rd;
|
||||
ok = rd.read_bin(path.str()) ;
|
||||
VERIFY( ok);
|
||||
COMPARE(rd.get_version(), 7); // should be version 7 since indices are < 2^16
|
||||
COMPARE(rd.get_gbs_center(), center);
|
||||
COMPARE(rd.get_gbs_radius(), 12345);
|
||||
COMPARE(rd.get_wgs84_nodes().size(), points.size());
|
||||
|
||||
comparePoints(rd, points);
|
||||
compareTexCoords(rd, texCoords);
|
||||
}
|
||||
|
||||
void test_many_tcs()
|
||||
{
|
||||
SGBinObject basic;
|
||||
SGPath path(simgear::Dir::current().file("many_tex.btg.gz"));
|
||||
|
||||
SGVec3d center(1, 2, 3);
|
||||
basic.set_gbs_center(center);
|
||||
basic.set_gbs_radius(12345);
|
||||
|
||||
std::vector<SGVec3d> points;
|
||||
generate_points(10000, points);
|
||||
std::vector<SGVec3f> normals;
|
||||
generate_normals(1024, normals);
|
||||
std::vector<SGVec2f> texCoords;
|
||||
generate_tcs(100000, texCoords);
|
||||
|
||||
basic.set_wgs84_nodes(points);
|
||||
basic.set_normals(normals);
|
||||
basic.set_texcoords(texCoords);
|
||||
|
||||
generate_tris(basic, 20000);
|
||||
|
||||
bool ok = basic.write_bin_file(path);
|
||||
VERIFY( ok );
|
||||
|
||||
SGBinObject rd;
|
||||
ok = rd.read_bin(path.str()) ;
|
||||
VERIFY( ok);
|
||||
COMPARE(rd.get_version(), 10); // should be version 10 since indices are > 2^16
|
||||
COMPARE(rd.get_wgs84_nodes().size(), points.size());
|
||||
COMPARE(rd.get_texcoords().size(), texCoords.size());
|
||||
|
||||
comparePoints(rd, points);
|
||||
compareTexCoords(rd, texCoords);
|
||||
compareTris(basic, rd);
|
||||
}
|
||||
|
||||
void test_big()
|
||||
{
|
||||
SGBinObject basic;
|
||||
SGPath path(simgear::Dir::current().file("big.btg.gz"));
|
||||
|
||||
SGVec3d center(1, 2, 3);
|
||||
basic.set_gbs_center(center);
|
||||
basic.set_gbs_radius(12345);
|
||||
|
||||
std::vector<SGVec3d> points;
|
||||
generate_points(200000, points);
|
||||
std::vector<SGVec3f> normals;
|
||||
generate_normals(1024, normals);
|
||||
std::vector<SGVec2f> texCoords;
|
||||
generate_tcs(300000, texCoords);
|
||||
|
||||
basic.set_wgs84_nodes(points);
|
||||
basic.set_normals(normals);
|
||||
basic.set_texcoords(texCoords);
|
||||
|
||||
generate_tris(basic, 200000);
|
||||
|
||||
bool ok = basic.write_bin_file(path);
|
||||
VERIFY( ok );
|
||||
|
||||
SGBinObject rd;
|
||||
ok = rd.read_bin(path.str()) ;
|
||||
VERIFY( ok);
|
||||
COMPARE(rd.get_version(), 10); // should be version 10 since indices are > 2^16
|
||||
COMPARE(rd.get_wgs84_nodes().size(), points.size());
|
||||
COMPARE(rd.get_texcoords().size(), texCoords.size());
|
||||
|
||||
comparePoints(rd, points);
|
||||
compareTexCoords(rd, texCoords);
|
||||
compareTris(basic, rd);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
test_empty();
|
||||
test_basic();
|
||||
test_many_tcs();
|
||||
test_big();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -41,3 +41,8 @@ target_link_libraries(test_tabbed_values sgmisc)
|
||||
add_executable(test_strings strutils_test.cxx )
|
||||
add_test(test_strings ${EXECUTABLE_OUTPUT_PATH}/test_strings)
|
||||
target_link_libraries(test_strings sgmisc)
|
||||
|
||||
add_executable(test_path path_test.cxx )
|
||||
add_test(test_path ${EXECUTABLE_OUTPUT_PATH}/test_path)
|
||||
target_link_libraries(test_path sgmisc sgdebug)
|
||||
|
||||
|
||||
144
simgear/misc/path_test.cxx
Normal file
144
simgear/misc/path_test.cxx
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
#define COMPARE(a, b) \
|
||||
if ((a) != (b)) { \
|
||||
cerr << "failed:" << #a << " != " << #b << endl; \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#define VERIFY(a) \
|
||||
if (!(a)) { \
|
||||
cerr << "failed:" << #a << endl; \
|
||||
exit(1); \
|
||||
}
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/misc/sg_dir.hxx>
|
||||
|
||||
void test_dir()
|
||||
{
|
||||
simgear::Dir temp = simgear::Dir::tempDir("foo");
|
||||
cout << "created:" << temp.path().str() << endl;
|
||||
|
||||
VERIFY(temp.exists());
|
||||
VERIFY(temp.path().isDir());
|
||||
VERIFY(!temp.path().isFile());
|
||||
|
||||
SGPath fileInDir = temp.file("foobaz");
|
||||
VERIFY(!fileInDir.exists());
|
||||
|
||||
if (!temp.remove(true)) {
|
||||
cout << "remove failed!" << endl;
|
||||
}
|
||||
|
||||
cout << temp.path().modTime() << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
SGPath pa;
|
||||
VERIFY(pa.isNull());
|
||||
COMPARE(pa.exists(), false);
|
||||
|
||||
// test basic parsing
|
||||
SGPath pb("/Foo/bar/something.png");
|
||||
COMPARE(pb.str(), std::string("/Foo/bar/something.png"));
|
||||
COMPARE(strcmp(pb.c_str(), "/Foo/bar/something.png"), 0);
|
||||
COMPARE(pb.dir(), std::string("/Foo/bar"));
|
||||
COMPARE(pb.file(), std::string("something.png"));
|
||||
COMPARE(pb.base(), std::string("/Foo/bar/something"));
|
||||
COMPARE(pb.file_base(), std::string("something"));
|
||||
COMPARE(pb.extension(), std::string("png"));
|
||||
VERIFY(pb.isAbsolute());
|
||||
VERIFY(!pb.isRelative());
|
||||
|
||||
// relative paths
|
||||
SGPath ra("where/to/begin.txt");
|
||||
COMPARE(ra.str(), std::string("where/to/begin.txt"));
|
||||
COMPARE(ra.dir(), std::string("where/to"));
|
||||
COMPARE(ra.file(), std::string("begin.txt"));
|
||||
COMPARE(ra.file_base(), std::string("begin"));
|
||||
VERIFY(!ra.isAbsolute());
|
||||
VERIFY(ra.isRelative());
|
||||
|
||||
// dots in paths / missing extensions
|
||||
SGPath pk("/Foo/bar.dot/thing");
|
||||
COMPARE(pk.dir(), std::string("/Foo/bar.dot"));
|
||||
COMPARE(pk.file(), std::string("thing"));
|
||||
COMPARE(pk.base(), std::string("/Foo/bar.dot/thing"));
|
||||
COMPARE(pk.file_base(), std::string("thing"));
|
||||
COMPARE(pk.extension(), std::string());
|
||||
|
||||
// multiple file extensions
|
||||
SGPath pj("/Foo/zot.dot/thing.tar.gz");
|
||||
COMPARE(pj.dir(), std::string("/Foo/zot.dot"));
|
||||
COMPARE(pj.file(), std::string("thing.tar.gz"));
|
||||
COMPARE(pj.base(), std::string("/Foo/zot.dot/thing"));
|
||||
COMPARE(pj.file_base(), std::string("thing"));
|
||||
COMPARE(pj.extension(), std::string("gz"));
|
||||
COMPARE(pj.complete_lower_extension(), std::string("tar.gz"));
|
||||
|
||||
// path fixing
|
||||
SGPath rd("where\\to\\begin.txt");
|
||||
COMPARE(rd.str(), std::string("where/to/begin.txt"));
|
||||
|
||||
// test modification
|
||||
// append
|
||||
SGPath d1("/usr/local");
|
||||
SGPath pc = d1;
|
||||
COMPARE(pc.str(), std::string("/usr/local"));
|
||||
pc.append("include");
|
||||
|
||||
COMPARE(pc.str(), std::string("/usr/local/include"));
|
||||
COMPARE(pc.file(), std::string("include"));
|
||||
|
||||
// add
|
||||
pc.add("/opt/local");
|
||||
COMPARE(pc.str(), std::string("/usr/local/include/:/opt/local"));
|
||||
|
||||
// concat
|
||||
SGPath pd = pb;
|
||||
pd.concat("-1");
|
||||
COMPARE(pd.str(), std::string("/Foo/bar/something.png-1"));
|
||||
|
||||
// create with relative path
|
||||
SGPath rb(d1, "include/foo");
|
||||
COMPARE(rb.str(), std::string("/usr/local/include/foo"));
|
||||
VERIFY(rb.isAbsolute());
|
||||
|
||||
// lower-casing of file extensions
|
||||
SGPath extA("FOO.ZIP");
|
||||
COMPARE(extA.base(), "FOO");
|
||||
COMPARE(extA.extension(), "ZIP");
|
||||
COMPARE(extA.lower_extension(), "zip");
|
||||
COMPARE(extA.complete_lower_extension(), "zip");
|
||||
|
||||
SGPath extB("BAH/FOO.HTML.GZ");
|
||||
COMPARE(extB.extension(), "GZ");
|
||||
COMPARE(extB.base(), "BAH/FOO");
|
||||
COMPARE(extB.lower_extension(), "gz");
|
||||
COMPARE(extB.complete_lower_extension(), "html.gz");
|
||||
#ifdef _WIN32
|
||||
COMPARE(d1.str_native(), std::string("\\usr\\local"));
|
||||
|
||||
SGPath winAbs("C:\\Windows\\System32");
|
||||
COMPARE(winAbs.str(), std::string("C:/Windows/System32"));
|
||||
#else
|
||||
COMPARE(d1.str_native(), std::string("/usr/local"));
|
||||
#endif
|
||||
|
||||
test_dir();
|
||||
|
||||
cout << "all tests passed OK" << endl;
|
||||
return 0; // passed
|
||||
}
|
||||
|
||||
@@ -18,33 +18,89 @@
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/misc/sg_dir.hxx>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# include <direct.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <dirent.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
Dir::Dir()
|
||||
{
|
||||
}
|
||||
|
||||
Dir::Dir(const SGPath& path) :
|
||||
_path(path)
|
||||
{
|
||||
_path.set_cached(false); // disable caching, so create/remove work
|
||||
}
|
||||
|
||||
Dir::Dir(const Dir& rel, const SGPath& relPath) :
|
||||
_path(rel.file(relPath.str()))
|
||||
{
|
||||
_path.set_cached(false); // disable caching, so create/remove work
|
||||
}
|
||||
|
||||
Dir Dir::current()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char* buf = _getcwd(NULL, 0);
|
||||
#else
|
||||
char* buf = ::getcwd(NULL, 0);
|
||||
#endif
|
||||
SGPath p(buf);
|
||||
free(buf);
|
||||
return Dir(p);
|
||||
}
|
||||
|
||||
Dir Dir::tempDir(const std::string& templ)
|
||||
{
|
||||
#ifdef HAVE_MKDTEMP
|
||||
char buf[1024];
|
||||
char* tempPath = ::getenv("TMPDIR");
|
||||
if (!tempPath) {
|
||||
tempPath = "/tmp/";
|
||||
}
|
||||
// Mac OS-X / BSD manual says any number of 'X's, but GLibc manual
|
||||
// says exactly six, so that's what I'm going with
|
||||
::snprintf(buf, 1024, "%s%s-XXXXXX", tempPath, templ.c_str());
|
||||
if (!mkdtemp(buf)) {
|
||||
SG_LOG(SG_IO, SG_WARN, "mkdtemp failed:" << strerror(errno));
|
||||
return Dir();
|
||||
}
|
||||
|
||||
return Dir(SGPath(buf));
|
||||
#else
|
||||
SGPath p(tempnam(0, templ.c_str()));
|
||||
Dir t(p);
|
||||
if (!t.create(0700)) {
|
||||
SG_LOG(SG_IO, SG_WARN, "failed to create temporary directory at " << p.str());
|
||||
}
|
||||
|
||||
return t;
|
||||
#endif
|
||||
}
|
||||
|
||||
PathList Dir::children(int types, const std::string& nameFilter) const
|
||||
@@ -175,8 +231,79 @@ bool Dir::exists() const
|
||||
SGPath Dir::file(const std::string& name) const
|
||||
{
|
||||
SGPath childPath = _path;
|
||||
childPath.set_cached(true);
|
||||
childPath.append(name);
|
||||
return childPath;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
# define sgMkDir(d,m) _mkdir(d)
|
||||
#else
|
||||
# define sgMkDir(d,m) mkdir(d,m)
|
||||
#endif
|
||||
|
||||
bool Dir::create(mode_t mode)
|
||||
{
|
||||
if (exists()) {
|
||||
return false; // already exists
|
||||
}
|
||||
|
||||
// recursively create parent directories
|
||||
Dir pr(parent());
|
||||
if (!pr.exists()) {
|
||||
bool ok = pr.create(mode);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// finally, create ourselves
|
||||
int err = sgMkDir(_path.c_str(), mode);
|
||||
if (err) {
|
||||
SG_LOG(SG_IO, SG_WARN, "directory creation failed: (" << _path.str() << ") " << strerror(errno) );
|
||||
}
|
||||
|
||||
return (err == 0);
|
||||
}
|
||||
|
||||
bool Dir::remove(bool recursive)
|
||||
{
|
||||
if (!exists()) {
|
||||
SG_LOG(SG_IO, SG_WARN, "attempt to remove non-existant dir:" << _path.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recursive) {
|
||||
bool ok;
|
||||
PathList cs = children(NO_DOT_OR_DOTDOT | INCLUDE_HIDDEN | TYPE_FILE | TYPE_DIR);
|
||||
BOOST_FOREACH(SGPath path, cs) {
|
||||
if (path.isDir()) {
|
||||
Dir childDir(path);
|
||||
ok = childDir.remove(true);
|
||||
} else {
|
||||
ok = path.remove();
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
} // of child iteration
|
||||
} // of recursive deletion
|
||||
|
||||
#ifdef _WIN32
|
||||
int err = _rmdir(_path.c_str());
|
||||
#else
|
||||
int err = rmdir(_path.c_str());
|
||||
#endif
|
||||
if (err) {
|
||||
SG_LOG(SG_IO, SG_WARN, "rmdir failed:" << _path.str() << ":" << strerror(errno));
|
||||
}
|
||||
return (err == 0);
|
||||
}
|
||||
|
||||
Dir Dir::parent() const
|
||||
{
|
||||
return Dir(_path.dir());
|
||||
}
|
||||
|
||||
} // of namespace simgear
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef int mode_t;
|
||||
#endif
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
typedef std::vector<SGPath> PathList;
|
||||
@@ -38,6 +42,15 @@ namespace simgear
|
||||
class Dir
|
||||
{
|
||||
public:
|
||||
Dir();
|
||||
|
||||
static Dir current();
|
||||
|
||||
/**
|
||||
* create a temporary directory, using the supplied name
|
||||
*/
|
||||
static Dir tempDir(const std::string& templ);
|
||||
|
||||
Dir(const SGPath& path);
|
||||
Dir(const Dir& rel, const SGPath& relPath);
|
||||
|
||||
@@ -53,10 +66,31 @@ namespace simgear
|
||||
|
||||
SGPath file(const std::string& name) const;
|
||||
|
||||
SGPath path() const
|
||||
{ return _path; }
|
||||
|
||||
/**
|
||||
* create the directory (and any parents as required) with the
|
||||
* request mode, or return failure
|
||||
*/
|
||||
bool create(mode_t mode);
|
||||
|
||||
/**
|
||||
* remove the directory.
|
||||
* If recursive is true, contained files and directories are
|
||||
* recursively removed
|
||||
*/
|
||||
bool remove(bool recursive = false);
|
||||
|
||||
/**
|
||||
* Check that the directory at the path exists (and is a directory!)
|
||||
*/
|
||||
bool exists() const;
|
||||
|
||||
/**
|
||||
* parent directory, if one exists
|
||||
*/
|
||||
Dir parent() const;
|
||||
private:
|
||||
mutable SGPath _path;
|
||||
};
|
||||
|
||||
@@ -28,13 +28,16 @@
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <direct.h>
|
||||
#endif
|
||||
#include "sg_path.hxx"
|
||||
|
||||
using std::string;
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
using std::string;
|
||||
|
||||
/**
|
||||
* define directory path separators
|
||||
@@ -58,14 +61,14 @@ SGPath::fix()
|
||||
{
|
||||
for ( string::size_type i = 0; i < path.size(); ++i ) {
|
||||
#if defined( WIN32 )
|
||||
// for windoze, don't replace the ":" for the second character
|
||||
if ( i == 1 ) {
|
||||
continue;
|
||||
}
|
||||
// for windoze, don't replace the ":" for the second character
|
||||
if ( i == 1 ) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if ( path[i] == sgDirPathSepBad ) {
|
||||
path[i] = sgDirPathSep;
|
||||
}
|
||||
if ( path[i] == sgDirPathSepBad ) {
|
||||
path[i] = sgDirPathSep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +76,8 @@ SGPath::fix()
|
||||
// default constructor
|
||||
SGPath::SGPath()
|
||||
: path(""),
|
||||
_cached(false)
|
||||
_cached(false),
|
||||
_cacheEnabled(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -81,7 +85,8 @@ SGPath::SGPath()
|
||||
// create a path based on "path"
|
||||
SGPath::SGPath( const std::string& p )
|
||||
: path(p),
|
||||
_cached(false)
|
||||
_cached(false),
|
||||
_cacheEnabled(true)
|
||||
{
|
||||
fix();
|
||||
}
|
||||
@@ -89,7 +94,8 @@ SGPath::SGPath( const std::string& p )
|
||||
// create a path based on "path" and a "subpath"
|
||||
SGPath::SGPath( const SGPath& p, const std::string& r )
|
||||
: path(p.path),
|
||||
_cached(false)
|
||||
_cached(false),
|
||||
_cacheEnabled(p._cacheEnabled)
|
||||
{
|
||||
append(r);
|
||||
fix();
|
||||
@@ -98,9 +104,11 @@ SGPath::SGPath( const SGPath& p, const std::string& r )
|
||||
SGPath::SGPath(const SGPath& p) :
|
||||
path(p.path),
|
||||
_cached(p._cached),
|
||||
_cacheEnabled(p._cacheEnabled),
|
||||
_exists(p._exists),
|
||||
_isDir(p._isDir),
|
||||
_isFile(p._isFile)
|
||||
_isFile(p._isFile),
|
||||
_modTime(p._modTime)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -108,9 +116,11 @@ SGPath& SGPath::operator=(const SGPath& p)
|
||||
{
|
||||
path = p.path;
|
||||
_cached = p._cached;
|
||||
_cacheEnabled = p._cacheEnabled;
|
||||
_exists = p._exists;
|
||||
_isDir = p._isDir;
|
||||
_isFile = p._isFile;
|
||||
_modTime = p._modTime;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -126,16 +136,20 @@ void SGPath::set( const string& p ) {
|
||||
_cached = false;
|
||||
}
|
||||
|
||||
void SGPath::set_cached(bool cached)
|
||||
{
|
||||
_cacheEnabled = cached;
|
||||
}
|
||||
|
||||
// append another piece to the existing path
|
||||
void SGPath::append( const string& p ) {
|
||||
if ( path.size() == 0 ) {
|
||||
path = p;
|
||||
path = p;
|
||||
} else {
|
||||
if ( p[0] != sgDirPathSep ) {
|
||||
path += sgDirPathSep;
|
||||
}
|
||||
path += p;
|
||||
if ( p[0] != sgDirPathSep ) {
|
||||
path += sgDirPathSep;
|
||||
}
|
||||
path += p;
|
||||
}
|
||||
fix();
|
||||
_cached = false;
|
||||
@@ -151,9 +165,9 @@ void SGPath::add( const string& p ) {
|
||||
// path separator
|
||||
void SGPath::concat( const string& p ) {
|
||||
if ( path.size() == 0 ) {
|
||||
path = p;
|
||||
path = p;
|
||||
} else {
|
||||
path += p;
|
||||
path += p;
|
||||
}
|
||||
fix();
|
||||
_cached = false;
|
||||
@@ -164,9 +178,9 @@ void SGPath::concat( const string& p ) {
|
||||
string SGPath::file() const {
|
||||
int index = path.rfind(sgDirPathSep);
|
||||
if (index >= 0) {
|
||||
return path.substr(index + 1);
|
||||
return path.substr(index + 1);
|
||||
} else {
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,20 +189,45 @@ string SGPath::file() const {
|
||||
string SGPath::dir() const {
|
||||
int index = path.rfind(sgDirPathSep);
|
||||
if (index >= 0) {
|
||||
return path.substr(0, index);
|
||||
return path.substr(0, index);
|
||||
} else {
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// get the base part of the path (everything but the extension.)
|
||||
string SGPath::base() const {
|
||||
int index = path.rfind(".");
|
||||
if ((index >= 0) && (path.find("/", index) == string::npos)) {
|
||||
return path.substr(0, index);
|
||||
unsigned int index = path.rfind(sgDirPathSep);
|
||||
if (index == string::npos) {
|
||||
index = 0; // no separator in the name
|
||||
} else {
|
||||
return "";
|
||||
++index; // skip past the separator
|
||||
}
|
||||
|
||||
// find the first dot after the final separator
|
||||
unsigned int firstDot = path.find(".", index);
|
||||
if (firstDot == string::npos) {
|
||||
return path; // no extension, return whole path
|
||||
}
|
||||
|
||||
return path.substr(0, firstDot);
|
||||
}
|
||||
|
||||
string SGPath::file_base() const
|
||||
{
|
||||
unsigned int index = path.rfind(sgDirPathSep);
|
||||
if (index == string::npos) {
|
||||
index = 0; // no separator in the name
|
||||
} else {
|
||||
++index; // skip past the separator
|
||||
}
|
||||
|
||||
unsigned int firstDot = path.find(".", index);
|
||||
if (firstDot == string::npos) {
|
||||
return path.substr(index); // no extensions
|
||||
}
|
||||
|
||||
return path.substr(index, firstDot - index);
|
||||
}
|
||||
|
||||
// get the extension (everything after the final ".")
|
||||
@@ -197,15 +236,36 @@ string SGPath::base() const {
|
||||
string SGPath::extension() const {
|
||||
int index = path.rfind(".");
|
||||
if ((index >= 0) && (path.find("/", index) == string::npos)) {
|
||||
return path.substr(index + 1);
|
||||
return path.substr(index + 1);
|
||||
} else {
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
string SGPath::lower_extension() const {
|
||||
return boost::to_lower_copy(extension());
|
||||
}
|
||||
|
||||
string SGPath::complete_lower_extension() const
|
||||
{
|
||||
unsigned int index = path.rfind(sgDirPathSep);
|
||||
if (index == string::npos) {
|
||||
index = 0; // no separator in the name
|
||||
} else {
|
||||
++index; // skip past the separator
|
||||
}
|
||||
|
||||
int firstDot = path.find(".", index);
|
||||
if ((firstDot >= 0) && (path.find(sgDirPathSep, firstDot) == string::npos)) {
|
||||
return boost::to_lower_copy(path.substr(firstDot + 1));
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void SGPath::validate() const
|
||||
{
|
||||
if (_cached) {
|
||||
if (_cached && _cacheEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -221,6 +281,7 @@ void SGPath::validate() const
|
||||
_exists = true;
|
||||
_isFile = ((S_IFREG & buf.st_mode ) !=0);
|
||||
_isDir = ((S_IFDIR & buf.st_mode ) !=0);
|
||||
_modTime = buf.st_mtime;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -232,6 +293,7 @@ void SGPath::validate() const
|
||||
_exists = true;
|
||||
_isFile = ((S_ISREG(buf.st_mode )) != 0);
|
||||
_isDir = ((S_ISDIR(buf.st_mode )) != 0);
|
||||
_modTime = buf.st_mtime;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -383,3 +445,29 @@ std::string SGPath::str_native() const
|
||||
return str();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SGPath::remove()
|
||||
{
|
||||
int err = ::unlink(c_str());
|
||||
if (err) {
|
||||
SG_LOG(SG_IO, SG_WARN, "file remove failed: (" << str() << ") " << strerror(errno));
|
||||
}
|
||||
return (err == 0);
|
||||
}
|
||||
|
||||
time_t SGPath::modTime() const
|
||||
{
|
||||
validate();
|
||||
return _modTime;
|
||||
}
|
||||
|
||||
bool SGPath::operator==(const SGPath& other) const
|
||||
{
|
||||
return (path == other.path);
|
||||
}
|
||||
|
||||
bool SGPath::operator!=(const SGPath& other) const
|
||||
{
|
||||
return (path != other.path);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
|
||||
@@ -49,10 +50,6 @@
|
||||
|
||||
class SGPath {
|
||||
|
||||
private:
|
||||
|
||||
std::string path;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor */
|
||||
@@ -86,6 +83,15 @@ public:
|
||||
void set( const std::string& p );
|
||||
SGPath& operator= ( const char* p ) { this->set(p); return *this; }
|
||||
|
||||
bool operator==(const SGPath& other) const;
|
||||
bool operator!=(const SGPath& other) const;
|
||||
|
||||
/**
|
||||
* Set if file information (exists, type, mod-time) is cached or
|
||||
* retrieved each time it is queried. Caching is enabled by default
|
||||
*/
|
||||
void set_cached(bool cached);
|
||||
|
||||
/**
|
||||
* Append another piece to the existing path. Inserts a path
|
||||
* separator between the existing component and the new component.
|
||||
@@ -123,12 +129,33 @@ public:
|
||||
*/
|
||||
std::string base() const;
|
||||
|
||||
/**
|
||||
* Get the base part of the filename (everything before the first '.')
|
||||
* @return the base filename
|
||||
*/
|
||||
std::string file_base() const;
|
||||
|
||||
/**
|
||||
* Get the extension part of the path (everything after the final ".")
|
||||
* @return the extension string
|
||||
*/
|
||||
std::string extension() const;
|
||||
|
||||
|
||||
/**
|
||||
* Get the extension part of the path (everything after the final ".")
|
||||
* converted to lowercase
|
||||
* @return the extension string
|
||||
*/
|
||||
std::string lower_extension() const;
|
||||
|
||||
/**
|
||||
* Get the complete extension part of the path (everything after the first ".")
|
||||
* this might look like 'tar.gz' or 'txt.Z', or might be identical to 'extension' above
|
||||
* the extension is converted to lowercase.
|
||||
* @return the extension string
|
||||
*/
|
||||
std::string complete_lower_extension() const;
|
||||
|
||||
/**
|
||||
* Get the path string
|
||||
* @return path string
|
||||
@@ -176,16 +203,30 @@ public:
|
||||
* check for default constructed path
|
||||
*/
|
||||
bool isNull() const;
|
||||
|
||||
/**
|
||||
* delete the file, if possible
|
||||
*/
|
||||
bool remove();
|
||||
|
||||
/**
|
||||
* modification time of the file
|
||||
*/
|
||||
time_t modTime() const;
|
||||
private:
|
||||
|
||||
void fix();
|
||||
|
||||
void validate() const;
|
||||
|
||||
mutable bool _cached;
|
||||
mutable bool _exists;
|
||||
mutable bool _isDir;
|
||||
mutable bool _isFile;
|
||||
std::string path;
|
||||
|
||||
mutable bool _cached : 1;
|
||||
bool _cacheEnabled : 1; ///< cacheing can be disbled if required
|
||||
mutable bool _exists : 1;
|
||||
mutable bool _isDir : 1;
|
||||
mutable bool _isFile : 1;
|
||||
mutable time_t _modTime;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -259,6 +259,26 @@ namespace simgear {
|
||||
return result;
|
||||
}
|
||||
|
||||
int compare_versions(const string& v1, const string& v2)
|
||||
{
|
||||
vector<string> v1parts(split(v1, "."));
|
||||
vector<string> v2parts(split(v2, "."));
|
||||
|
||||
int lastPart = std::min(v1parts.size(), v2parts.size());
|
||||
for (int part=0; part < lastPart; ++part) {
|
||||
int part1 = to_int(v1parts[part]);
|
||||
int part2 = to_int(v2parts[part]);
|
||||
|
||||
if (part1 != part2) {
|
||||
return part1 - part2;
|
||||
}
|
||||
} // of parts iteration
|
||||
|
||||
// reached end - longer wins
|
||||
return v1parts.size() - v2parts.size();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace strutils
|
||||
|
||||
} // end namespace simgear
|
||||
|
||||
@@ -127,6 +127,14 @@ namespace simgear {
|
||||
* convert a string representing a decimal number, to an int
|
||||
*/
|
||||
int to_int(const std::string& s, int base = 10);
|
||||
|
||||
/**
|
||||
* Like strcmp(), but for dotted versions strings NN.NN.NN
|
||||
* any number of terms are support.
|
||||
* @return 0 if versions match, -ve number if v1 is lower, +ve if v1
|
||||
* is greater
|
||||
*/
|
||||
int compare_versions(const std::string& v1, const std::string& v2);
|
||||
} // end namespace strutils
|
||||
} // end namespace simgear
|
||||
|
||||
|
||||
@@ -53,6 +53,16 @@ int main (int ac, char ** av)
|
||||
COMPARE(to_int("0000000"), 0);
|
||||
COMPARE(to_int("-10000"), -10000);
|
||||
|
||||
VERIFY(compare_versions("1.0.12", "1.1") < 0);
|
||||
VERIFY(compare_versions("1.1", "1.0.12") > 0);
|
||||
VERIFY(compare_versions("10.6.7", "10.6.7") == 0);
|
||||
VERIFY(compare_versions("2.0", "2.0.99") < 0);
|
||||
VERIFY(compare_versions("99", "99") == 0);
|
||||
VERIFY(compare_versions("99", "98") > 0);
|
||||
|
||||
// since we compare numerically, leasing zeros shouldn't matter
|
||||
VERIFY(compare_versions("0.06.7", "0.6.07") == 0);
|
||||
|
||||
cout << "all tests passed successfully!" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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 T>
|
||||
class SGPropertyChangeCallback
|
||||
: public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
SGPropertyChangeCallback(T* obj, void (T::*method)(SGPropertyNode*),
|
||||
SGPropertyNode_ptr property,bool initial=false)
|
||||
: _obj(obj), _callback(method), _property(property)
|
||||
{
|
||||
_property->addChangeListener(this,initial);
|
||||
}
|
||||
virtual ~SGPropertyChangeCallback()
|
||||
{
|
||||
_property->removeChangeListener(this);
|
||||
}
|
||||
void valueChanged (SGPropertyNode * node)
|
||||
{
|
||||
(_obj->*_callback)(node);
|
||||
}
|
||||
private:
|
||||
T* _obj;
|
||||
void (T::*_callback)(SGPropertyNode*);
|
||||
SGPropertyNode_ptr _property;
|
||||
};
|
||||
|
||||
#endif // __PROPS_HXX
|
||||
|
||||
// end of props.hxx
|
||||
|
||||
@@ -25,6 +25,7 @@ SGModelPlacement::SGModelPlacement () :
|
||||
_selector(new osg::Switch),
|
||||
_transform(new osg::PositionAttitudeTransform)
|
||||
{
|
||||
_selector->addChild(_transform.get());
|
||||
}
|
||||
|
||||
SGModelPlacement::~SGModelPlacement ()
|
||||
@@ -34,10 +35,11 @@ SGModelPlacement::~SGModelPlacement ()
|
||||
void
|
||||
SGModelPlacement::init( osg::Node * model )
|
||||
{
|
||||
// remove previous model (in case of reinit)
|
||||
_transform->removeChild(0,1);
|
||||
if (model != 0) {
|
||||
_transform->addChild(model);
|
||||
}
|
||||
_selector->addChild(_transform.get());
|
||||
_selector->setValue(0, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,20 +110,24 @@ void CloudShaderGeometry::drawImplementation(RenderInfo& renderInfo) const
|
||||
const CloudSprite& t = _cloudsprites[itr->idx];
|
||||
GLfloat ua1[3] = { (GLfloat) t.texture_index_x/varieties_x,
|
||||
(GLfloat) t.texture_index_y/varieties_y,
|
||||
(GLfloat) t.width };
|
||||
(GLfloat) t.width };
|
||||
GLfloat ua2[3] = { (GLfloat) t.height,
|
||||
(GLfloat) t.shade,
|
||||
(GLfloat) t.cloud_height };
|
||||
(GLfloat) shade_factor,
|
||||
(GLfloat) cloud_height };
|
||||
GLfloat ua3[3] = { (GLfloat) bottom_factor,
|
||||
(GLfloat) middle_factor,
|
||||
(GLfloat) top_factor };
|
||||
|
||||
extensions->glVertexAttrib3fv(USR_ATTR_1, ua1 );
|
||||
extensions->glVertexAttrib3fv(USR_ATTR_2, ua2 );
|
||||
extensions->glVertexAttrib3fv(USR_ATTR_3, ua3 );
|
||||
glColor4f(t.position.x(), t.position.y(), t.position.z(), zscale);
|
||||
_geometry->draw(renderInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void CloudShaderGeometry::addSprite(const SGVec3f& p, int tx, int ty,
|
||||
float w, float h,
|
||||
float s, float cull, float cloud_height)
|
||||
float w, float h, float cull)
|
||||
{
|
||||
// Only add the sprite if it is further than the cull distance to all other sprites
|
||||
// except for the center sprite.
|
||||
@@ -137,8 +141,8 @@ void CloudShaderGeometry::addSprite(const SGVec3f& p, int tx, int ty,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_cloudsprites.push_back(CloudSprite(p, tx, ty, w, h, s, cloud_height));
|
||||
|
||||
_cloudsprites.push_back(CloudSprite(p, tx, ty, w, h));
|
||||
}
|
||||
|
||||
bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
|
||||
@@ -166,13 +170,13 @@ bool CloudShaderGeometry_readLocalData(Object& obj, Input& fr)
|
||||
while (!fr.eof() && fr[0].getNoNestedBrackets() > entry) {
|
||||
SGVec3f v;
|
||||
int tx, ty;
|
||||
float w, h, s, ch;
|
||||
float w, h;
|
||||
if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())
|
||||
&& fr[2].getFloat(v.z()) && fr[3].getInt(tx) && fr[4].getInt(ty) &&
|
||||
fr[5].getFloat(w) && fr[6].getFloat(h)&& fr[7].getFloat(s) && fr[8].getFloat(ch)) {
|
||||
fr[5].getFloat(w) && fr[6].getFloat(h)) {
|
||||
fr += 5;
|
||||
//SGVec3f* v = new SGVec3f(v.x(), v.y(), v.z());
|
||||
geom._cloudsprites.push_back(CloudShaderGeometry::CloudSprite(v, tx, ty, w, h,s,ch));
|
||||
geom._cloudsprites.push_back(CloudShaderGeometry::CloudSprite(v, tx, ty, w, h));
|
||||
} else {
|
||||
++fr;
|
||||
}
|
||||
@@ -197,8 +201,7 @@ bool CloudShaderGeometry_writeLocalData(const Object& obj, Output& fw)
|
||||
fw.indent() << itr->position.x() << " " << itr->position.y() << " "
|
||||
<< itr->position.z() << " " << itr->texture_index_x << " "
|
||||
<< itr->texture_index_y << " " << itr->width << " "
|
||||
<< itr->height << " " << itr->shade
|
||||
<< itr->cloud_height << " "<< std::endl;
|
||||
<< itr->height << " " << std::endl;
|
||||
}
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
|
||||
@@ -46,14 +46,15 @@ class CloudShaderGeometry : public osg::Drawable
|
||||
|
||||
const static unsigned int USR_ATTR_1 = 10;
|
||||
const static unsigned int USR_ATTR_2 = 11;
|
||||
|
||||
const static unsigned int USR_ATTR_3 = 12;
|
||||
|
||||
CloudShaderGeometry()
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
}
|
||||
|
||||
CloudShaderGeometry(int vx, int vy, float width, float height, float zsc) :
|
||||
varieties_x(vx), varieties_y(vy), zscale(zsc)
|
||||
CloudShaderGeometry(int vx, int vy, float width, float height, float ts, float ms, float bs, float shade, float ch, float zsc) :
|
||||
varieties_x(vx), varieties_y(vy), top_factor(ts), middle_factor(ms), bottom_factor(bs), shade_factor(shade), cloud_height(ch), zscale(zsc)
|
||||
{
|
||||
setUseDisplayList(false);
|
||||
float x = width/2.0f;
|
||||
@@ -69,9 +70,8 @@ class CloudShaderGeometry : public osg::Drawable
|
||||
META_Object(flightgear, CloudShaderGeometry);
|
||||
|
||||
struct CloudSprite {
|
||||
CloudSprite(const SGVec3f& p, int tx, int ty, float w, float h,
|
||||
float s, float ch) :
|
||||
position(p), texture_index_x(tx), texture_index_y(ty), width(w), height(h), shade(s), cloud_height(ch)
|
||||
CloudSprite(const SGVec3f& p, int tx, int ty, float w, float h) :
|
||||
position(p), texture_index_x(tx), texture_index_y(ty), width(w), height(h)
|
||||
{ }
|
||||
|
||||
SGVec3f position;
|
||||
@@ -79,8 +79,6 @@ class CloudShaderGeometry : public osg::Drawable
|
||||
int texture_index_y;
|
||||
float width;
|
||||
float height;
|
||||
float shade;
|
||||
float cloud_height;
|
||||
};
|
||||
|
||||
typedef std::vector<CloudSprite> CloudSpriteList;
|
||||
@@ -88,8 +86,8 @@ class CloudShaderGeometry : public osg::Drawable
|
||||
|
||||
void insert(const CloudSprite& t)
|
||||
{ _cloudsprites.push_back(t); }
|
||||
void insert(SGVec3f& p, int tx, int ty, float w, float h, float s, float ch)
|
||||
{ insert(CloudSprite(p, tx, ty, w, h, s, ch)); }
|
||||
void insert(SGVec3f& p, int tx, int ty, float w, float h)
|
||||
{ insert(CloudSprite(p, tx, ty, w, h)); }
|
||||
|
||||
unsigned getNumCloudSprite() const
|
||||
{ return _cloudsprites.size(); }
|
||||
@@ -107,15 +105,19 @@ class CloudShaderGeometry : public osg::Drawable
|
||||
_geometry = geometry;
|
||||
}
|
||||
|
||||
void addSprite(const SGVec3f& p, int tx, int ty, float w, float h,
|
||||
float s, float cull, float cloud_height);
|
||||
void addSprite(const SGVec3f& p, int tx, int ty, float w, float h, float cull);
|
||||
|
||||
osg::ref_ptr<osg::Drawable> _geometry;
|
||||
|
||||
int varieties_x;
|
||||
int varieties_y;
|
||||
float top_factor;
|
||||
float middle_factor;
|
||||
float bottom_factor;
|
||||
float shade_factor;
|
||||
float cloud_height;
|
||||
float zscale;
|
||||
|
||||
|
||||
// Bounding box extents.
|
||||
osg::BoundingBox _bbox;
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ void SGCloudField::addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> t
|
||||
float lon, float lat, float alt, float x, float y) {
|
||||
|
||||
// Get the base position
|
||||
SGGeod loc = SGGeod::fromDegFt(lon, lat, alt);
|
||||
SGGeod loc = SGGeod::fromDegFt(lon, lat, 0.0);
|
||||
|
||||
// Determine any shift by x/y
|
||||
if ((x != 0.0f) || (y != 0.0f)) {
|
||||
@@ -248,24 +248,24 @@ void SGCloudField::addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> t
|
||||
|
||||
SGGeod base_pos = SGGeod::fromDegFt(lon, lat, 0.0f);
|
||||
SGGeodesy::direct(base_pos, crs, dst, loc, endcrs);
|
||||
|
||||
// The direct call provides the position at 0 alt, so adjust as required.
|
||||
loc.setElevationFt(alt);
|
||||
}
|
||||
|
||||
// The direct call provides the position at 0 alt, so adjust as required.
|
||||
loc.setElevationFt(alt);
|
||||
|
||||
// Work out where this cloud should go in OSG coordinates.
|
||||
SGVec3<double> cart;
|
||||
SGGeodesy::SGGeodToCart(loc, cart);
|
||||
osg::Vec3f pos = toOsg(cart);
|
||||
|
||||
// Convert to the scenegraph orientation where we just rotate around
|
||||
// the y axis 180 degrees.
|
||||
osg::Quat orient = toOsg(SGQuatd::fromLonLatDeg(lon, lat) * SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0)));
|
||||
|
||||
if (old_pos == osg::Vec3f(0.0f, 0.0f, 0.0f)) {
|
||||
// First se tup.
|
||||
// First setup.
|
||||
SGVec3<double> fieldcenter;
|
||||
SGGeodesy::SGGeodToCart(SGGeod::fromDegFt(lon, lat, 0.0f), fieldcenter);
|
||||
SGGeodesy::SGGeodToCart(SGGeod::fromDegFt(loc.getLongitudeDeg(), loc.getLatitudeDeg(), 0.0f), fieldcenter);
|
||||
// Convert to the scenegraph orientation where we just rotate around
|
||||
// the y axis 180 degrees.
|
||||
osg::Quat orient = toOsg(SGQuatd::fromLonLatDeg(loc.getLongitudeDeg(), loc.getLatitudeDeg()) * SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0)));
|
||||
|
||||
field_transform->setPosition(toOsg(fieldcenter));
|
||||
field_transform->setAttitude(orient);
|
||||
@@ -274,7 +274,8 @@ void SGCloudField::addCloudToTree(osg::ref_ptr<osg::PositionAttitudeTransform> t
|
||||
|
||||
pos = pos - field_transform->getPosition();
|
||||
|
||||
pos = orient.inverse() * pos;
|
||||
//pos = orient.inverse() * pos;
|
||||
pos = field_transform->getAttitude().inverse() * pos;
|
||||
|
||||
// We have a two level dynamic quad tree which the cloud will be added
|
||||
// to. If there are no appropriate nodes in the quad tree, they are
|
||||
|
||||
@@ -60,6 +60,8 @@
|
||||
|
||||
using namespace simgear;
|
||||
using namespace osg;
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -67,24 +69,36 @@ typedef std::map<std::string, osg::ref_ptr<Effect> > EffectMap;
|
||||
EffectMap effectMap;
|
||||
}
|
||||
|
||||
double SGNewCloud::sprite_density = 1.0;
|
||||
float SGNewCloud::sprite_density = 1.0;
|
||||
|
||||
SGNewCloud::SGNewCloud(const SGPath &texture_root, const SGPropertyNode *cld_def)
|
||||
{
|
||||
min_width = cld_def->getDoubleValue("min-cloud-width-m", 500.0);
|
||||
max_width = cld_def->getDoubleValue("max-cloud-width-m", min_width*2);
|
||||
min_height = cld_def->getDoubleValue("min-cloud-height-m", 400.0);
|
||||
max_height = cld_def->getDoubleValue("max-cloud-height-m", min_height*2);
|
||||
min_sprite_width = cld_def->getDoubleValue("min-sprite-width-m", 200.0);
|
||||
max_sprite_width = cld_def->getDoubleValue("max-sprite-width-m", min_sprite_width*1.5);
|
||||
min_sprite_height = cld_def->getDoubleValue("min-sprite-height-m", 150);
|
||||
max_sprite_height = cld_def->getDoubleValue("max-sprite-height-m", min_sprite_height*1.5);
|
||||
min_width = cld_def->getFloatValue("min-cloud-width-m", 500.0);
|
||||
max_width = cld_def->getFloatValue("max-cloud-width-m", min_width*2);
|
||||
min_height = cld_def->getFloatValue("min-cloud-height-m", 400.0);
|
||||
max_height = cld_def->getFloatValue("max-cloud-height-m", min_height*2);
|
||||
min_sprite_width = cld_def->getFloatValue("min-sprite-width-m", 200.0);
|
||||
max_sprite_width = cld_def->getFloatValue("max-sprite-width-m", min_sprite_width*1.5);
|
||||
min_sprite_height = cld_def->getFloatValue("min-sprite-height-m", 150);
|
||||
max_sprite_height = cld_def->getFloatValue("max-sprite-height-m", min_sprite_height*1.5);
|
||||
num_sprites = cld_def->getIntValue("num-sprites", 20);
|
||||
num_textures_x = cld_def->getIntValue("num-textures-x", 4);
|
||||
num_textures_y = cld_def->getIntValue("num-textures-y", 4);
|
||||
height_map_texture = cld_def->getBoolValue("height-map-texture", false);
|
||||
bottom_shade = cld_def->getDoubleValue("bottom-shade", 1.0);
|
||||
zscale = cld_def->getDoubleValue("z-scale", 1.0);
|
||||
|
||||
min_bottom_lighting_factor = cld_def->getFloatValue("min-bottom-lighting-factor", 1.0);
|
||||
max_bottom_lighting_factor = cld_def->getFloatValue("max-bottom-lighting-factor", min(min_bottom_lighting_factor + 0.1, 1.0));
|
||||
|
||||
min_middle_lighting_factor = cld_def->getFloatValue("min-middle-lighting-factor", 1.0);
|
||||
max_middle_lighting_factor = cld_def->getFloatValue("max-middle-lighting-factor", min(min_middle_lighting_factor + 0.1, 1.0));
|
||||
|
||||
min_top_lighting_factor = cld_def->getFloatValue("min-top-lighting-factor", 1.0);
|
||||
max_top_lighting_factor = cld_def->getFloatValue("max-top-lighting-factor", min(min_top_lighting_factor + 0.1, 1.0));
|
||||
|
||||
min_shade_lighting_factor = cld_def->getFloatValue("min-shade-lighting-factor", 0.5);
|
||||
max_shade_lighting_factor = cld_def->getFloatValue("max-shade-lighting-factor", min(min_shade_lighting_factor + 0.1, 1.0));
|
||||
|
||||
zscale = cld_def->getFloatValue("z-scale", 1.0);
|
||||
texture = cld_def->getStringValue("texture", "cl_cumulus.png");
|
||||
|
||||
// Create a new Effect for the texture, if required.
|
||||
@@ -167,24 +181,40 @@ osg::ref_ptr<EffectGeode> SGNewCloud::genCloud() {
|
||||
|
||||
osg::ref_ptr<EffectGeode> geode = new EffectGeode;
|
||||
|
||||
CloudShaderGeometry* sg = new CloudShaderGeometry(num_textures_x,
|
||||
num_textures_y,
|
||||
max_width + max_sprite_width,
|
||||
max_height + max_sprite_height,
|
||||
zscale);
|
||||
|
||||
// Determine how big this specific cloud instance is. Note that we subtract
|
||||
// the sprite size because the width/height is used to define the limits of
|
||||
// the center of the sprites, not their edges.
|
||||
float width = min_width + sg_random() * (max_width - min_width) - min_sprite_width;
|
||||
float height = min_height + sg_random() * (max_height - min_height) - min_sprite_height;
|
||||
|
||||
if (width < 0.0) { width = 0.0; }
|
||||
if (height < 0.0) { height = 0.0; }
|
||||
|
||||
// Determine appropriate shading factors
|
||||
float top_factor = min_top_lighting_factor + sg_random() * (max_top_lighting_factor - min_top_lighting_factor);
|
||||
float middle_factor = min_middle_lighting_factor + sg_random() * (max_middle_lighting_factor - min_middle_lighting_factor);
|
||||
float bottom_factor = min_bottom_lighting_factor + sg_random() * (max_bottom_lighting_factor - min_bottom_lighting_factor);
|
||||
float shade_factor = min_shade_lighting_factor + sg_random() * (max_shade_lighting_factor - min_shade_lighting_factor);
|
||||
|
||||
//printf("Cloud: %2f, %2f, %2f, %2f\n", top_factor, middle_factor, bottom_factor, shade_factor);
|
||||
|
||||
CloudShaderGeometry* sg = new CloudShaderGeometry(num_textures_x,
|
||||
num_textures_y,
|
||||
max_width + max_sprite_width,
|
||||
max_height + max_sprite_height,
|
||||
top_factor,
|
||||
middle_factor,
|
||||
bottom_factor,
|
||||
shade_factor,
|
||||
height,
|
||||
zscale);
|
||||
|
||||
// Determine the cull distance. This is used to remove sprites that are too close together.
|
||||
// The value is squared as we use vector calculations.
|
||||
float cull_distance_squared = min_sprite_height * min_sprite_height * 0.1f;
|
||||
|
||||
// The number of sprites we actually use is a function of the (user-controlled) density
|
||||
int n_sprites = num_sprites * sprite_density * (0.5 + sg_random());
|
||||
int n_sprites = num_sprites * sprite_density * (0.5f + sg_random());
|
||||
|
||||
for (int i = 0; i < n_sprites; i++)
|
||||
{
|
||||
@@ -202,8 +232,8 @@ osg::ref_ptr<EffectGeode> SGNewCloud::genCloud() {
|
||||
y = 0;
|
||||
z = height * 0.5;
|
||||
} else {
|
||||
double theta = sg_random() * SGD_2PI;
|
||||
double elev = sg_random() * SGD_PI;
|
||||
float theta = sg_random() * SGD_2PI;
|
||||
float elev = sg_random() * SGD_PI;
|
||||
x = width * cos(theta) * 0.5f * sin(elev);
|
||||
y = width * sin(theta) * 0.5f * sin(elev);
|
||||
z = height * cos(elev) * 0.5f + height * 0.5f;
|
||||
@@ -235,7 +265,7 @@ osg::ref_ptr<EffectGeode> SGNewCloud::genCloud() {
|
||||
|
||||
// Determine the sprite texture indexes.
|
||||
int index_x = (int) floor(sg_random() * num_textures_x);
|
||||
if (index_x == num_textures_x) { index_x--; }
|
||||
if (index_x >= num_textures_x) { index_x = num_textures_x - 1; }
|
||||
|
||||
int index_y = (int) floor(sg_random() * num_textures_y);
|
||||
|
||||
@@ -243,20 +273,17 @@ osg::ref_ptr<EffectGeode> SGNewCloud::genCloud() {
|
||||
// The y index depends on the position of the sprite within the cloud.
|
||||
// This allows cloud designers to have particular sprites for the base
|
||||
// and tops of the cloud.
|
||||
index_y = (int) floor((z / height + 0.5f) * num_textures_y);
|
||||
index_y = (int) floor((z / height) * num_textures_y);
|
||||
}
|
||||
|
||||
if (index_y == num_textures_y) { index_y--; }
|
||||
|
||||
if (index_y >= num_textures_y) { index_y = num_textures_y - 1; }
|
||||
|
||||
sg->addSprite(SGVec3f(x, y, z),
|
||||
index_x,
|
||||
index_y,
|
||||
sprite_width,
|
||||
sprite_height,
|
||||
bottom_shade,
|
||||
cull_distance_squared,
|
||||
height * 0.5f);
|
||||
index_x,
|
||||
index_y,
|
||||
sprite_width,
|
||||
sprite_height,
|
||||
cull_distance_squared);
|
||||
}
|
||||
|
||||
sg->setGeometry(quad);
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
// Generate a Cloud
|
||||
osg::ref_ptr<simgear::EffectGeode> genCloud ();
|
||||
|
||||
static double getDensity(void)
|
||||
static float getDensity(void)
|
||||
{
|
||||
return sprite_density;
|
||||
}
|
||||
@@ -61,16 +61,37 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
double min_width;
|
||||
double max_width;
|
||||
double min_height;
|
||||
double max_height;
|
||||
double min_sprite_width;
|
||||
double max_sprite_width;
|
||||
double min_sprite_height;
|
||||
double max_sprite_height;
|
||||
double bottom_shade;
|
||||
double zscale;
|
||||
float min_width;
|
||||
float max_width;
|
||||
float min_height;
|
||||
float max_height;
|
||||
float min_sprite_width;
|
||||
float max_sprite_width;
|
||||
float min_sprite_height;
|
||||
float max_sprite_height;
|
||||
|
||||
// Minimum and maximum bottom, middle, top, sunny, shade lighting
|
||||
// factors. For individual clouds we choose a bottom/middle/top
|
||||
// shade from between each min/max value
|
||||
float min_bottom_lighting_factor;
|
||||
float max_bottom_lighting_factor;
|
||||
float min_middle_lighting_factor;
|
||||
float max_middle_lighting_factor;
|
||||
float min_top_lighting_factor;
|
||||
float max_top_lighting_factor;
|
||||
float min_shade_lighting_factor;
|
||||
float max_shade_lighting_factor;
|
||||
|
||||
// The density of the cloud is the shading applied
|
||||
// to cloud sprites on the opposite side of the cloud
|
||||
// from the sun. For an invidual cloud instance a value
|
||||
// between min_density and max_density is chosen.
|
||||
float min_density;
|
||||
float max_density;
|
||||
|
||||
// zscale indicates how sprites should be scaled vertically
|
||||
// after billboarding.
|
||||
float zscale;
|
||||
bool height_map_texture;
|
||||
int num_sprites;
|
||||
int num_textures_x;
|
||||
@@ -78,7 +99,7 @@ private:
|
||||
string texture;
|
||||
osg::Geometry* quad;
|
||||
osg::ref_ptr<simgear::Effect> effect;
|
||||
static double sprite_density;
|
||||
static float sprite_density;
|
||||
|
||||
osg::Geometry* createOrthQuad(float w, float h, int varieties_x, int varieties_y);
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ struct AddTreesLeafObject
|
||||
{
|
||||
void operator() (LOD* lod, const TreeBin::Tree& tree) const
|
||||
{
|
||||
Geode* geode = static_cast<Geode*>(lod->getChild(rand() % SG_TREE_FADE_OUT_LEVELS));
|
||||
Geode* geode = static_cast<Geode*>(lod->getChild(int(tree.position.x() * 10.0f) % lod->getNumChildren()));
|
||||
addTreeToLeafGeode(geode, tree.position);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
#endif
|
||||
|
||||
using namespace simgear;
|
||||
using namespace std;
|
||||
|
||||
const char* rsync_cmd =
|
||||
"rsync --verbose --archive --delete --perms --owner --group";
|
||||
|
||||
@@ -54,7 +54,7 @@ protected:
|
||||
void syncAirportsModels();
|
||||
void syncArea(int lat, int lon);
|
||||
void syncAreas(int lat, int lon, int lat_dir, int lon_dir);
|
||||
void refreshScenery(SGPath path,const string& relativeDir);
|
||||
void refreshScenery(SGPath path,const std::string& relativeDir);
|
||||
|
||||
class SvnThread;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#cmakedefine HAVE_TIMEGM
|
||||
#cmakedefine HAVE_ISNAN
|
||||
#cmakedefine HAVE_WINDOWS_H
|
||||
#cmakedefine HAVE_MKDTEMP
|
||||
|
||||
#cmakedefine HAVE_SVN_CLIENT_H
|
||||
#cmakedefine HAVE_LIBSVN_CLIENT_1
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
extern bool isNaN(float *v);
|
||||
|
||||
|
||||
@@ -1248,7 +1248,7 @@ namespace simgear
|
||||
ConvertExpression() {}
|
||||
ConvertExpression(::SGExpression<OpType>* expr0)
|
||||
{
|
||||
addOperand(expr0);
|
||||
this->addOperand(expr0);
|
||||
}
|
||||
virtual void eval(T& value, const simgear::expression::Binding* b) const
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user