Merge branch 'next' of git://gitorious.org/fg/simgear into next

This commit is contained in:
Erik Hofman
2011-10-18 18:32:57 +02:00
49 changed files with 2968 additions and 1473 deletions

View File

@@ -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})

View File

@@ -32,6 +32,7 @@ set(HLA_SOURCES
HLABasicDataType.cxx
HLADataElement.cxx
HLADataType.cxx
HLADataTypeVisitor.cxx
HLAEnumeratedDataElement.cxx
HLAEnumeratedDataType.cxx
HLAFederate.cxx

View File

@@ -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) :

View File

@@ -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 {

View 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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -35,6 +35,7 @@ libsghla_a_SOURCES = \
HLABasicDataType.cxx \
HLADataElement.cxx \
HLADataType.cxx \
HLADataTypeVisitor.cxx \
HLAEnumeratedDataElement.cxx \
HLAEnumeratedDataType.cxx \
HLAFederate.cxx \

View File

@@ -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

View File

@@ -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);

View File

@@ -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)
{
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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;

View File

@@ -39,6 +39,7 @@ RTIObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIDat
return;
}
hlaObjectClass->discoverInstance(objectInstance, tag);
objectInstance->requestObjectAttributeValueUpdate();
}
void

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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

View File

@@ -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
View 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;
}

View File

@@ -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
View 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
}

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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);
}

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
};

View File

@@ -86,6 +86,7 @@
#endif
using namespace simgear;
using namespace std;
const char* rsync_cmd =
"rsync --verbose --archive --delete --perms --owner --group";

View File

@@ -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;

View File

@@ -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

View File

@@ -47,6 +47,7 @@
#include <simgear/math/SGMath.hxx>
using std::string;
using std::vector;
extern bool isNaN(float *v);

View File

@@ -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
{