Skip to content

Commit

Permalink
[OMEdit] Distinguish length/radius scale invariance for vector visual…
Browse files Browse the repository at this point in the history
…izers (#11663)

* Include missing headers

* Reword scale-related parameters

* Change visibility through a distinct variable

* Split scale invariance into length and radius
  • Loading branch information
anotheruserofgithub committed Dec 4, 2023
1 parent 0933e87 commit 26f58c4
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 39 deletions.
8 changes: 5 additions & 3 deletions OMEdit/OMEditLIB/Animation/Vector.cpp
Expand Up @@ -62,11 +62,13 @@ std::ostream& operator<<(std::ostream& os, const VectorQuantity quantity)

VectorObject::VectorObject()
: AbstractVisualizerObjectWithVisualProperties(VisualizerType::vector),
mScaleLength(1.0),
mScaleRadius(1.0),
mScaleTransf(1.0),
mLengthScale(1.0),
mRadiusScale(1.0),
mAutoLengthScaleCancellation(1.0),
mAutoRadiusScaleCancellation(1.0),
mAutoScaleCancellationRequired(false),
mOnlyShaftLengthCounted(false),
mHidden(false),
_quantity(VisualizerAttribute(0.0)),
_headAtOrigin(VisualizerAttribute(0.0)),
_twoHeadedArrow(VisualizerAttribute(0.0))
Expand Down
37 changes: 22 additions & 15 deletions OMEdit/OMEditLIB/Animation/Vector.h
Expand Up @@ -53,28 +53,33 @@ class VectorObject final : public AbstractVisualizerObjectWithVisualProperties<V
VectorObject& operator=(const VectorObject&) = default;
VectorObject* asVector() override final {return this;}
void dumpVisualizerAttributes() override;
void setScaleLength(const float scale) {mScaleLength = scale;}
void setScaleRadius(const float scale) {mScaleRadius = scale;}
void setScaleTransf(const float scale) {mScaleTransf = scale;}
float getScaleTransf() const {return mScaleTransf;}
void setLengthScale(const float scale) {mLengthScale = scale;}
void setRadiusScale(const float scale) {mRadiusScale = scale;}
void setAutoLengthScaleCancellation(const float scale) {mAutoLengthScaleCancellation = scale;}
void setAutoRadiusScaleCancellation(const float scale) {mAutoRadiusScaleCancellation = scale;}
float getAutoLengthScaleCancellation() const {return mAutoLengthScaleCancellation;}
float getAutoRadiusScaleCancellation() const {return mAutoRadiusScaleCancellation;}
void setAutoScaleCancellationRequired(const bool autoScaleCancellationRequired) {mAutoScaleCancellationRequired = autoScaleCancellationRequired;}
bool getAutoScaleCancellationRequired() const {return mAutoScaleCancellationRequired;}
void setOnlyShaftLengthCounted(const bool onlyShaftLengthCounted) {mOnlyShaftLengthCounted = onlyShaftLengthCounted;}
bool hasOnlyShaftLengthCounted() const {return mOnlyShaftLengthCounted;}
void setInvisible() {mHidden = true;}
void setVisible() {mHidden = false;}
void setCoordinates(const float x, const float y, const float z) {_coords[0].exp = x, _coords[1].exp = y, _coords[2].exp = z;}
void getCoordinates(float* x, float* y, float* z) const {*x = _coords[0].exp, *y = _coords[1].exp, *z = _coords[2].exp;}
float getLength () const {return mScaleTransf * mScaleLength * std::sqrt(_coords[0].exp * _coords[0].exp + _coords[1].exp * _coords[1].exp + _coords[2].exp * _coords[2].exp);}
float getRadius () const {return mScaleTransf * mScaleRadius * kRadius ;}
float getHeadLength() const {return mScaleTransf * mScaleRadius * kHeadLength;}
float getHeadRadius() const {return mScaleTransf * mScaleRadius * kHeadRadius;}
float getLength () const {return mHidden ? 0 : mAutoLengthScaleCancellation * mLengthScale * std::sqrt(_coords[0].exp * _coords[0].exp + _coords[1].exp * _coords[1].exp + _coords[2].exp * _coords[2].exp);}
float getRadius () const {return mHidden ? 0 : mAutoRadiusScaleCancellation * mRadiusScale * kRadius;}
float getHeadLength() const {return mHidden ? 0 : mAutoRadiusScaleCancellation * mRadiusScale * kHeadLength;}
float getHeadRadius() const {return mHidden ? 0 : mAutoRadiusScaleCancellation * mRadiusScale * kHeadRadius;}
VectorQuantity getQuantity() const {return static_cast<VectorQuantity>(_quantity.exp);}
bool areCoordinatesConstant() const {return _coords[0].isConst && _coords[1].isConst && _coords[2].isConst;}
bool hasHeadAtOrigin() const {return _headAtOrigin.exp;}
bool isTwoHeadedArrow() const {return _twoHeadedArrow.exp;}
bool isAdjustableRadius() const {return getQuantity() != VectorQuantity::relativePosition;}
bool isAdjustableLength() const {return getQuantity() != VectorQuantity::relativePosition;}
bool isScaleInvariant () const {return getQuantity() != VectorQuantity::relativePosition;}
bool isDrawnOnTop () const {return getQuantity() != VectorQuantity::relativePosition;}
bool isDrawnOnTop () const {return getQuantity() != VectorQuantity::relativePosition;}
bool isLengthAdjustable () const {return getQuantity() != VectorQuantity::relativePosition;}
bool isRadiusAdjustable () const {return getQuantity() != VectorQuantity::relativePosition;}
bool isLengthScaleInvariant() const {return getQuantity() != VectorQuantity::relativePosition;}
bool isRadiusScaleInvariant() const {return getQuantity() != VectorQuantity::relativePosition;}
public:
static constexpr float kRadius = 0.0125; //!< Modelica.Mechanics.MultiBody.World.defaultArrowDiameter / 2 = 1 / 40 / 2 = 0.0125
static constexpr float kHeadLength = 0.1000; //!< Modelica.Mechanics.MultiBody.Types.Defaults.ArrowHeadLengthFraction * (2 * kRadius) = 4 * 0.025 = 0.1000
Expand All @@ -84,11 +89,13 @@ class VectorObject final : public AbstractVisualizerObjectWithVisualProperties<V
static constexpr char kAutoScaleRenderBinName[] = "RenderBin"; //!< See class RenderBinPrototypeList in osgUtil/RenderBin.cpp
static constexpr int kAutoScaleRenderBinNum = std::numeric_limits<int>::max(); //!< To be rendered last
private:
float mScaleLength;
float mScaleRadius;
float mScaleTransf;
float mLengthScale;
float mRadiusScale;
float mAutoLengthScaleCancellation;
float mAutoRadiusScaleCancellation;
bool mAutoScaleCancellationRequired;
bool mOnlyShaftLengthCounted;
bool mHidden;
public:
VisualizerAttribute _coords[3];
VisualizerAttribute _quantity;
Expand Down
58 changes: 37 additions & 21 deletions OMEdit/OMEditLIB/Animation/Visualization.cpp
Expand Up @@ -43,6 +43,7 @@

#include <osg/Array>
#include <osg/Drawable>
#include <osg/Geometry>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osg/StateAttribute>
Expand All @@ -57,9 +58,11 @@
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <exception>
#include <functional>
#include <limits>
#include <map>
#include <typeinfo>
#include <unordered_map>
#include <vector>

Expand Down Expand Up @@ -787,7 +790,7 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex*
std::vector<std::reference_wrapper<VectorObject>> fixedRadiusVectors;
std::vector<std::reference_wrapper<VectorObject>> adjustableRadiusVectors;
for (VectorObject& vector : _vectors) {
if (vector.isAdjustableRadius()) {
if (vector.isRadiusAdjustable()) {
adjustableRadiusVectors.push_back(vector);
} else {
fixedRadiusVectors.push_back(vector);
Expand Down Expand Up @@ -872,7 +875,7 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex*

// Apply the radius scale to all adjustable-radius vectors
for (VectorObject& vector : adjustableRadiusVectors) {
vector.setScaleRadius(scale);
vector.setRadiusScale(scale);
updateVisualizer(vector);
}

Expand All @@ -886,7 +889,7 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex*
// Initialize a container of adjustable-length vectors
std::vector<std::reference_wrapper<VectorObject>> adjustableLengthVectors;
for (VectorObject& vector : _vectors) {
if (vector.isAdjustableLength()) {
if (vector.isLengthAdjustable()) {
adjustableLengthVectors.push_back(vector);
}
}
Expand All @@ -904,20 +907,14 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex*
numberOfSamples[vector] = timeSamples > 0 && (timeIncrement <= 0 || vector.areCoordinatesConstant()) ? 1 : timeSamples;
}

// Initialize a map of actual transform scales, one for each adjustable-length vector
std::unordered_map<const std::reference_wrapper<VectorObject>, float> transformScales;
for (VectorObject& vector : adjustableLengthVectors) {
transformScales[vector] = vector.getScaleTransf();
}

// Store whether only the shaft length is counted for all adjustable-length vectors
for (VectorObject& vector : adjustableLengthVectors) {
vector.setOnlyShaftLengthCounted(!countUpToApex);
}

// Update the bounds of the whole scene without any adjustable-length vectors
for (VectorObject& vector : adjustableLengthVectors) {
vector.setScaleTransf(0);
vector.setInvisible();
updateVisualizer(vector);
}

Expand Down Expand Up @@ -956,7 +953,7 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex*
// Make the vectors of the current quantity visible again
// (the update is not necessary here because it is done inside and after the while loop in any case)
for (VectorObject& vector : vectors) {
vector.setScaleTransf(transformScales[vector]);
vector.setVisible();
}

// Adjust the length scale for the current quantity as long as the criteria have not been met
Expand Down Expand Up @@ -988,7 +985,7 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex*

// Apply the new length scale to the vectors of the current quantity
for (VectorObject& vector : vectors) {
vector.setScaleLength(scale);
vector.setLengthScale(scale);
updateVisualizer(vector);
}

Expand Down Expand Up @@ -1064,14 +1061,14 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex*
// Make the vectors of the current quantity invisible again
// (until all length scales have been carefully adjusted)
for (VectorObject& vector : vectors) {
vector.setScaleTransf(0);
vector.setInvisible();
updateVisualizer(vector);
}
}

// Update the bounds of the whole scene with all adjustable-length vectors using their adjusted length scales
for (VectorObject& vector : adjustableLengthVectors) {
vector.setScaleTransf(transformScales[vector]);
vector.setVisible();
updateVisualizer(vector);
}

Expand All @@ -1089,7 +1086,7 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex*

// Make all adjustable-length vectors invisible
for (VectorObject& vector : adjustableLengthVectors) {
vector.setScaleTransf(0);
vector.setInvisible();
updateVisualizer(vector);
}

Expand All @@ -1098,7 +1095,7 @@ void OMVisualBase::chooseVectorScales(osgViewer::View* view, OpenThreads::Mutex*

// Make all adjustable-length vectors visible
for (VectorObject& vector : adjustableLengthVectors) {
vector.setScaleTransf(transformScales[vector]);
vector.setVisible();
updateVisualizer(vector);
}
}
Expand Down Expand Up @@ -1154,9 +1151,25 @@ void AutoTransformCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv
}
if (visualizer && visualizer->isVector()) {
VectorObject* vector = visualizer->asVector();
const float scale = 1 / at->getScale().z(); // See osg::AutoTransform::accept(osg::NodeVisitor&) or in later versions osg::AutoTransform::computeMatrix(const osg::NodeVisitor*) (since OSG commit 92092a5)
bool update = false;
if (vector->getAutoScaleCancellationRequired()) {
vector->setAutoScaleCancellationRequired(false);
vector->setScaleTransf(1 / at->getScale().z()); // See osg::AutoTransform::accept(osg::NodeVisitor&) or in later versions osg::AutoTransform::computeMatrix(const osg::NodeVisitor*) (since OSG commit 92092a5)
vector->setAutoRadiusScaleCancellation(scale);
vector->setAutoLengthScaleCancellation(scale);
update = true;
} else if (vector->isLengthScaleInvariant() && !vector->isRadiusScaleInvariant()) {
if (vector->getAutoRadiusScaleCancellation() != scale) {
vector->setAutoRadiusScaleCancellation(scale);
update = true;
}
} else if (vector->isRadiusScaleInvariant() && !vector->isLengthScaleInvariant()) {
if (vector->getAutoLengthScaleCancellation() != scale) {
vector->setAutoLengthScaleCancellation(scale);
update = true;
}
}
if (update) {
_visualization->getBaseData()->updateVisualizer(vector);
}
}
Expand Down Expand Up @@ -1394,14 +1407,17 @@ void OSGScene::setUpScene(std::vector<VectorObject>& vectors)
{
for (VectorObject& vector : vectors)
{
const bool isScaleInvariant = vector.isLengthScaleInvariant() || vector.isRadiusScaleInvariant();
const bool isDrawnOnTop = vector.isDrawnOnTop();

osg::ref_ptr<AutoTransformVisualizer> transf = new AutoTransformVisualizer(&vector);
transf->setName(vector._id);
transf->setAutoRotateMode(osg::AutoTransform::NO_ROTATION);
transf->setAutoScaleTransitionWidthRatio(0);
transf->setAutoScaleToScreen(vector.isScaleInvariant());
transf->setCullingActive(!vector.isScaleInvariant()); // Work-around for osg::AutoTransform::setAutoScaleToScreen(bool) (see OSG commit 5c48904)
transf->getOrCreateStateSet()->setMode(GL_NORMALIZE, vector.isScaleInvariant() ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
transf->getOrCreateStateSet()->setRenderBinDetails(VectorObject::kAutoScaleRenderBinNum - !vector.isDrawnOnTop(), VectorObject::kAutoScaleRenderBinName);
transf->setAutoScaleToScreen(isScaleInvariant);
transf->setCullingActive(!isScaleInvariant); // Work-around for osg::AutoTransform::setAutoScaleToScreen(bool) (see OSG commit 5c48904)
transf->getOrCreateStateSet()->setMode(GL_NORMALIZE, isScaleInvariant ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
transf->getOrCreateStateSet()->setRenderBinDetails(VectorObject::kAutoScaleRenderBinNum - !isDrawnOnTop, VectorObject::kAutoScaleRenderBinName);
transf->addCullCallback(_atCullCallback.get());

osg::ref_ptr<osg::ShapeDrawable> shapeDraw0 = new osg::ShapeDrawable(); // shaft cylinder
Expand Down
1 change: 1 addition & 0 deletions OMEdit/OMEditLIB/Animation/Visualization.h
Expand Up @@ -45,6 +45,7 @@
#include <QOpenGLContext> // must be included before OSG headers

#include <osg/Version>
#include <osg/Uniform>
#include <osg/Transform>
#include <osg/AutoTransform>
#include <osg/MatrixTransform>
Expand Down

0 comments on commit 26f58c4

Please sign in to comment.