From 3e8aeccc8735df1a83b6cbc5fc0b9f34fbd92044 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Sat, 8 Feb 2014 12:39:43 +0100 Subject: [PATCH] New textrapezoid TexTransformAnimation. Allows trapezoid texture transformations, as needed for example to correct for the tilt angle of HUD combiners. --- simgear/scene/model/animation.cxx | 235 ++++++++++++++++++------------ simgear/scene/model/animation.hxx | 21 ++- 2 files changed, 161 insertions(+), 95 deletions(-) diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 30cab2e3..a3ebc774 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -35,7 +35,6 @@ #include #include - #include #include #include @@ -48,6 +47,8 @@ #include #include +#include "vg/vgu.h" + #include "animation.hxx" #include "model.hxx" @@ -533,17 +534,26 @@ SGAnimation::installInGroup(const std::string& name, osg::Group& group, } //------------------------------------------------------------------------------ -SGVec3d SGAnimation::readVec3( const std::string& name, +SGVec3d SGAnimation::readVec3( const SGPropertyNode& cfg, + const std::string& name, const std::string& suffix, const SGVec3d& def ) const { SGVec3d vec; - vec[0] = _configNode->getDoubleValue(name + "/x" + suffix, def.x()); - vec[1] = _configNode->getDoubleValue(name + "/y" + suffix, def.y()); - vec[2] = _configNode->getDoubleValue(name + "/z" + suffix, def.z()); + vec[0] = cfg.getDoubleValue(name + "/x" + suffix, def.x()); + vec[1] = cfg.getDoubleValue(name + "/y" + suffix, def.y()); + vec[2] = cfg.getDoubleValue(name + "/z" + suffix, def.z()); return vec; } +//------------------------------------------------------------------------------ +SGVec3d SGAnimation::readVec3( const std::string& name, + const std::string& suffix, + const SGVec3d& def ) const +{ + return readVec3(*_configNode, name, suffix, def); +} + //------------------------------------------------------------------------------ // factored out to share with SGKnobAnimation void SGAnimation::readRotationCenterAndAxis( SGVec3d& center, @@ -2025,6 +2035,61 @@ private: SGVec3d _center; }; +class SGTexTransformAnimation::Trapezoid : + public SGTexTransformAnimation::Transform { +public: + + enum Side { TOP, RIGHT, BOTTOM, LEFT }; + + Trapezoid(Side side): + _side(side) + { } + virtual void transform(osg::Matrix& matrix) + { + VGfloat sx0 = 0, sy0 = 0, + sx1 = 1, sy1 = 0, + sx2 = 0, sy2 = 1, + sx3 = 1, sy3 = 1; + switch( _side ) + { + case TOP: + sx0 -= _value; + sx1 += _value; + break; + case RIGHT: + sy1 -= _value; + sy3 += _value; + break; + case BOTTOM: + sx2 -= _value; + sx3 += _value; + break; + case LEFT: + sy0 -= _value; + sy2 += _value; + break; + } + VGfloat mat[3][3]; + VGUErrorCode err = vguComputeWarpQuadToSquare( sx0, sy0, + sx1, sy1, + sx2, sy2, + sx3, sy3, + (VGfloat*)mat ); + if( err != VGU_NO_ERROR ) + return; + + matrix.preMult( osg::Matrix( + mat[0][0], mat[0][1], 0, mat[0][2], + mat[1][0], mat[1][1], 0, mat[1][2], + 0, 0, 1, 0, + mat[2][0], mat[2][1], 0, mat[2][2] + )); + } + +protected: + Side _side; +}; + class SGTexTransformAnimation::UpdateCallback : public osg::StateAttribute::Callback { public: @@ -2084,18 +2149,22 @@ SGTexTransformAnimation::createAnimationGroup(osg::Group& parent) std::string type = getType(); if (type == "textranslate") { - appendTexTranslate(getConfig(), updateCallback); + appendTexTranslate(*getConfig(), updateCallback); } else if (type == "texrotate") { - appendTexRotate(getConfig(), updateCallback); + appendTexRotate(*getConfig(), updateCallback); + } else if (type == "textrapezoid") { + appendTexTrapezoid(*getConfig(), updateCallback); } else if (type == "texmultiple") { std::vector > transformConfigs; transformConfigs = getConfig()->getChildren("transform"); for (unsigned i = 0; i < transformConfigs.size(); ++i) { std::string subtype = transformConfigs[i]->getStringValue("subtype", ""); if (subtype == "textranslate") - appendTexTranslate(transformConfigs[i], updateCallback); + appendTexTranslate(*transformConfigs[i], updateCallback); else if (subtype == "texrotate") - appendTexRotate(transformConfigs[i], updateCallback); + appendTexRotate(*transformConfigs[i], updateCallback); + else if (subtype == "textrapezoid") + appendTexTrapezoid(*transformConfigs[i], updateCallback); else SG_LOG(SG_INPUT, SG_ALERT, "Ignoring unknown texture transform subtype"); @@ -2110,102 +2179,86 @@ SGTexTransformAnimation::createAnimationGroup(osg::Group& parent) return group; } -void -SGTexTransformAnimation::appendTexTranslate(const SGPropertyNode* config, - UpdateCallback* updateCallback) +SGExpressiond* +SGTexTransformAnimation::readValue( const SGPropertyNode& cfg, + const std::string& suffix ) { - std::string propertyName = config->getStringValue("property", ""); + std::string prop_name = cfg.getStringValue("property"); SGSharedPtr value; - if (propertyName.empty()) + if( prop_name.empty() ) value = new SGConstExpression(0); - else { - SGPropertyNode* inputProperty = getModelRoot()->getNode(propertyName, true); - value = new SGPropertyExpression(inputProperty); - } + else + value = new SGPropertyExpression + ( + getModelRoot()->getNode(prop_name, true) + ); - SGInterpTable* table = read_interpolation_table(config); - if (table) { + SGInterpTable* table = read_interpolation_table(&cfg); + if( table ) + { value = new SGInterpTableExpression(value, table); - double biasValue = config->getDoubleValue("bias", 0); - if (biasValue != 0) + double biasValue = cfg.getDoubleValue("bias", 0); + if( biasValue ) + value = new SGBiasExpression(value, biasValue); + value = new SGStepExpression( value, + cfg.getDoubleValue("step", 0), + cfg.getDoubleValue("scroll", 0) ); + } + else + { + double biasValue = cfg.getDoubleValue("bias", 0); + if( biasValue ) value = new SGBiasExpression(value, biasValue); value = new SGStepExpression(value, - config->getDoubleValue("step", 0), - config->getDoubleValue("scroll", 0)); - value = value->simplify(); - } else { - double biasValue = config->getDoubleValue("bias", 0); - if (biasValue != 0) - value = new SGBiasExpression(value, biasValue); - value = new SGStepExpression(value, - config->getDoubleValue("step", 0), - config->getDoubleValue("scroll", 0)); - value = read_offset_factor(config, value, "factor", "offset"); + cfg.getDoubleValue("step", 0), + cfg.getDoubleValue("scroll", 0)); + value = read_offset_factor(&cfg, value, "factor", "offset" + suffix); - if (config->hasChild("min") || config->hasChild("max")) { - double minClip = config->getDoubleValue("min", -SGLimitsd::max()); - double maxClip = config->getDoubleValue("max", SGLimitsd::max()); + if( cfg.hasChild("min" + suffix) + || cfg.hasChild("max" + suffix) ) + { + double minClip = cfg.getDoubleValue("min" + suffix, -SGLimitsd::max()); + double maxClip = cfg.getDoubleValue("max" + suffix, SGLimitsd::max()); value = new SGClipExpression(value, minClip, maxClip); } - value = value->simplify(); } - SGVec3d axis(config->getDoubleValue("axis/x", 0), - config->getDoubleValue("axis/y", 0), - config->getDoubleValue("axis/z", 0)); - Translation* translation; - translation = new Translation(normalize(axis)); - translation->setValue(config->getDoubleValue("starting-position", 0)); - updateCallback->appendTransform(translation, value); + + return value.release()->simplify(); } void -SGTexTransformAnimation::appendTexRotate(const SGPropertyNode* config, - UpdateCallback* updateCallback) +SGTexTransformAnimation::appendTexTranslate( const SGPropertyNode& cfg, + UpdateCallback* updateCallback ) { - std::string propertyName = config->getStringValue("property", ""); - SGSharedPtr value; - if (propertyName.empty()) - value = new SGConstExpression(0); - else { - SGPropertyNode* inputProperty = getModelRoot()->getNode(propertyName, true); - value = new SGPropertyExpression(inputProperty); - } - - SGInterpTable* table = read_interpolation_table(config); - if (table) { - value = new SGInterpTableExpression(value, table); - double biasValue = config->getDoubleValue("bias", 0); - if (biasValue != 0) - value = new SGBiasExpression(value, biasValue); - value = new SGStepExpression(value, - config->getDoubleValue("step", 0), - config->getDoubleValue("scroll", 0)); - value = value->simplify(); - } else { - double biasValue = config->getDoubleValue("bias", 0); - if (biasValue != 0) - value = new SGBiasExpression(value, biasValue); - value = new SGStepExpression(value, - config->getDoubleValue("step", 0), - config->getDoubleValue("scroll", 0)); - value = read_offset_factor(config, value, "factor", "offset-deg"); - - if (config->hasChild("min-deg") || config->hasChild("max-deg")) { - double minClip = config->getDoubleValue("min-deg", -SGLimitsd::max()); - double maxClip = config->getDoubleValue("max-deg", SGLimitsd::max()); - value = new SGClipExpression(value, minClip, maxClip); - } - value = value->simplify(); - } - SGVec3d axis(config->getDoubleValue("axis/x", 0), - config->getDoubleValue("axis/y", 0), - config->getDoubleValue("axis/z", 0)); - SGVec3d center(config->getDoubleValue("center/x", 0), - config->getDoubleValue("center/y", 0), - config->getDoubleValue("center/z", 0)); - Rotation* rotation; - rotation = new Rotation(normalize(axis), center); - rotation->setValue(config->getDoubleValue("starting-position-deg", 0)); - updateCallback->appendTransform(rotation, value); + Translation* translation = new Translation(normalize(readVec3(cfg, "axis"))); + translation->setValue(cfg.getDoubleValue("starting-position", 0)); + updateCallback->appendTransform(translation, readValue(cfg)); } +void +SGTexTransformAnimation::appendTexRotate( const SGPropertyNode& cfg, + UpdateCallback* updateCallback ) +{ + Rotation* rotation = new Rotation( normalize(readVec3(cfg, "axis")), + readVec3(cfg, "center") ); + rotation->setValue(cfg.getDoubleValue("starting-position-deg", 0)); + updateCallback->appendTransform(rotation, readValue(cfg, "-deg")); +} + +void +SGTexTransformAnimation::appendTexTrapezoid( const SGPropertyNode& cfg, + UpdateCallback* updateCallback ) +{ + Trapezoid::Side side = Trapezoid::TOP; + const std::string side_str = cfg.getStringValue("side"); + if( side_str == "right" ) + side = Trapezoid::RIGHT; + else if( side_str == "bottom" ) + side = Trapezoid::BOTTOM; + else if( side_str == "left" ) + side = Trapezoid::LEFT; + + Trapezoid* trapezoid = new Trapezoid(side); + trapezoid->setValue(cfg.getDoubleValue("starting-position", 0)); + updateCallback->appendTransform(trapezoid, readValue(cfg)); +} diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index 048d991f..1a093247 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -68,9 +68,15 @@ protected: * @param suffix Suffix appended to each child node (x,y,z) * @param def Vector containing default values */ + SGVec3d readVec3( const SGPropertyNode& cfg, + const std::string& name, + const std::string& suffix = "", + const SGVec3d& def = SGVec3d::zeros() ) const; + SGVec3d readVec3( const std::string& name, const std::string& suffix = "", const SGVec3d& def = SGVec3d::zeros() ) const; + void readRotationCenterAndAxis(SGVec3d& center, SGVec3d& axis) const; SGExpressiond* readOffsetValue(const char* tag_name) const; @@ -322,11 +328,18 @@ private: class Transform; class Translation; class Rotation; + class Trapezoid; class UpdateCallback; - void appendTexTranslate(const SGPropertyNode* config, - UpdateCallback* updateCallback); - void appendTexRotate(const SGPropertyNode* config, - UpdateCallback* updateCallback); + + SGExpressiond* readValue( const SGPropertyNode& cfg, + const std::string& suffix = "" ); + + void appendTexTranslate( const SGPropertyNode& cfg, + UpdateCallback* updateCallback); + void appendTexRotate( const SGPropertyNode& cfg, + UpdateCallback* updateCallback); + void appendTexTrapezoid( const SGPropertyNode& cfg, + UpdateCallback* updateCallback); };