Merge branch 'timoore/optimizations' into next
This commit is contained in:
@@ -31,9 +31,9 @@
|
|||||||
|
|
||||||
#include "SGRotateTransform.hxx"
|
#include "SGRotateTransform.hxx"
|
||||||
|
|
||||||
static void
|
void SGRotateTransform::set_rotation (osg::Matrix &matrix, double position_rad,
|
||||||
set_rotation (osg::Matrix &matrix, double position_rad,
|
const SGVec3d ¢er,
|
||||||
const SGVec3d ¢er, const SGVec3d &axis)
|
const SGVec3d &axis)
|
||||||
{
|
{
|
||||||
double temp_angle = -position_rad;
|
double temp_angle = -position_rad;
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ public:
|
|||||||
|
|
||||||
virtual osg::BoundingSphere computeBound() const;
|
virtual osg::BoundingSphere computeBound() const;
|
||||||
|
|
||||||
|
// Useful for other classes too.
|
||||||
|
static void set_rotation (osg::Matrix &matrix, double position_rad,
|
||||||
|
const SGVec3d ¢er, const SGVec3d &axis);
|
||||||
private:
|
private:
|
||||||
SGVec3d _center;
|
SGVec3d _center;
|
||||||
SGVec3d _axis;
|
SGVec3d _axis;
|
||||||
|
|||||||
+107
-100
@@ -44,6 +44,7 @@
|
|||||||
#include <simgear/structure/SGBinding.hxx>
|
#include <simgear/structure/SGBinding.hxx>
|
||||||
#include <simgear/scene/material/EffectGeode.hxx>
|
#include <simgear/scene/material/EffectGeode.hxx>
|
||||||
#include <simgear/scene/material/EffectCullVisitor.hxx>
|
#include <simgear/scene/material/EffectCullVisitor.hxx>
|
||||||
|
#include <simgear/scene/util/DeletionManager.hxx>
|
||||||
#include <simgear/scene/util/OsgMath.hxx>
|
#include <simgear/scene/util/OsgMath.hxx>
|
||||||
#include <simgear/scene/util/SGNodeMasks.hxx>
|
#include <simgear/scene/util/SGNodeMasks.hxx>
|
||||||
#include <simgear/scene/util/SGSceneUserData.hxx>
|
#include <simgear/scene/util/SGSceneUserData.hxx>
|
||||||
@@ -71,51 +72,6 @@ using namespace simgear;
|
|||||||
// Static utility functions.
|
// Static utility functions.
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up the transform matrix for a spin or rotation.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
set_rotation (osg::Matrix &matrix, double position_deg,
|
|
||||||
const SGVec3d ¢er, const SGVec3d &axis)
|
|
||||||
{
|
|
||||||
double temp_angle = -SGMiscd::deg2rad(position_deg);
|
|
||||||
|
|
||||||
double s = sin(temp_angle);
|
|
||||||
double c = cos(temp_angle);
|
|
||||||
double t = 1 - c;
|
|
||||||
|
|
||||||
// axis was normalized at load time
|
|
||||||
// hint to the compiler to put these into FP registers
|
|
||||||
double x = axis[0];
|
|
||||||
double y = axis[1];
|
|
||||||
double z = axis[2];
|
|
||||||
|
|
||||||
matrix(0, 0) = t * x * x + c ;
|
|
||||||
matrix(0, 1) = t * y * x - s * z ;
|
|
||||||
matrix(0, 2) = t * z * x + s * y ;
|
|
||||||
matrix(0, 3) = 0;
|
|
||||||
|
|
||||||
matrix(1, 0) = t * x * y + s * z ;
|
|
||||||
matrix(1, 1) = t * y * y + c ;
|
|
||||||
matrix(1, 2) = t * z * y - s * x ;
|
|
||||||
matrix(1, 3) = 0;
|
|
||||||
|
|
||||||
matrix(2, 0) = t * x * z - s * y ;
|
|
||||||
matrix(2, 1) = t * y * z + s * x ;
|
|
||||||
matrix(2, 2) = t * z * z + c ;
|
|
||||||
matrix(2, 3) = 0;
|
|
||||||
|
|
||||||
// hint to the compiler to put these into FP registers
|
|
||||||
x = center[0];
|
|
||||||
y = center[1];
|
|
||||||
z = center[2];
|
|
||||||
|
|
||||||
matrix(3, 0) = x - x*matrix(0, 0) - y*matrix(1, 0) - z*matrix(2, 0);
|
|
||||||
matrix(3, 1) = y - x*matrix(0, 1) - y*matrix(1, 1) - z*matrix(2, 1);
|
|
||||||
matrix(3, 2) = z - x*matrix(0, 2) - y*matrix(1, 2) - z*matrix(2, 2);
|
|
||||||
matrix(3, 3) = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up the transform matrix for a translation.
|
* Set up the transform matrix for a translation.
|
||||||
*/
|
*/
|
||||||
@@ -726,51 +682,81 @@ SGTranslateAnimation::createAnimationGroup(osg::Group& parent)
|
|||||||
// Implementation of rotate/spin animation
|
// Implementation of rotate/spin animation
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//Cull callback
|
class SGRotAnimTransform : public SGRotateTransform
|
||||||
class RotAnimCallback : public osg::NodeCallback
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RotAnimCallback(SGCondition const* condition,
|
SGRotAnimTransform();
|
||||||
SGExpressiond const* animationValue,
|
SGRotAnimTransform(const SGRotAnimTransform&,
|
||||||
double initialValue = 0.0) :
|
const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||||
_condition(condition),
|
META_Node(simgear, SGRotAnimTransform);
|
||||||
_animationValue(animationValue),
|
virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
|
||||||
_initialValue(initialValue),
|
osg::NodeVisitor* nv) const;
|
||||||
_lastValue(0.0)
|
virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
|
||||||
{ }
|
osg::NodeVisitor* nv) const;
|
||||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
|
||||||
public:
|
|
||||||
SGSharedPtr<SGCondition const> _condition;
|
SGSharedPtr<SGCondition const> _condition;
|
||||||
SGSharedPtr<SGExpressiond const> _animationValue;
|
SGSharedPtr<SGExpressiond const> _animationValue;
|
||||||
double _initialValue;
|
// used when condition is false
|
||||||
double _lastValue;
|
mutable double _lastAngle;
|
||||||
};
|
};
|
||||||
|
|
||||||
void RotAnimCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
SGRotAnimTransform::SGRotAnimTransform()
|
||||||
|
: _lastAngle(0.0)
|
||||||
{
|
{
|
||||||
using namespace osg;
|
}
|
||||||
SGRotateTransform* transform = static_cast<SGRotateTransform*>(node);
|
|
||||||
EffectCullVisitor* cv = dynamic_cast<EffectCullVisitor*>(nv);
|
|
||||||
|
|
||||||
if (!cv)
|
SGRotAnimTransform::SGRotAnimTransform(const SGRotAnimTransform& rhs,
|
||||||
return;
|
const osg::CopyOp& copyop)
|
||||||
|
: SGRotateTransform(rhs, copyop), _condition(rhs._condition),
|
||||||
|
_animationValue(rhs._animationValue), _lastAngle(rhs._lastAngle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SGRotAnimTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
|
||||||
|
osg::NodeVisitor* nv) const
|
||||||
|
{
|
||||||
double angle = 0.0;
|
double angle = 0.0;
|
||||||
if (!_condition || _condition->test()) {
|
if (!_condition || _condition->test()) {
|
||||||
angle = _animationValue->getValue() - _initialValue;
|
angle = _animationValue->getValue();
|
||||||
_lastValue = angle;
|
_lastAngle = angle;
|
||||||
} else {
|
} else {
|
||||||
angle = _lastValue;
|
angle = _lastAngle;
|
||||||
}
|
}
|
||||||
const SGVec3d& sgcenter = transform->getCenter();
|
double angleRad = SGMiscd::deg2rad(angle);
|
||||||
const SGVec3d& sgaxis = transform->getAxis();
|
if (_referenceFrame == RELATIVE_RF) {
|
||||||
Matrixd mat = Matrixd::translate(-sgcenter[0], -sgcenter[1], -sgcenter[2])
|
// FIXME optimize
|
||||||
* Matrixd::rotate(SGMiscd::deg2rad(angle), sgaxis[0], sgaxis[1], sgaxis[2])
|
osg::Matrix tmp;
|
||||||
* Matrixd::translate(sgcenter[0], sgcenter[1], sgcenter[2])
|
set_rotation(tmp, angleRad, getCenter(), getAxis());
|
||||||
* *cv->getModelViewMatrix();
|
matrix.preMult(tmp);
|
||||||
ref_ptr<RefMatrix> refmat = new RefMatrix(mat);
|
} else {
|
||||||
cv->pushModelViewMatrix(refmat.get(), transform->getReferenceFrame());
|
osg::Matrix tmp;
|
||||||
traverse(transform, nv);
|
SGRotateTransform::set_rotation(tmp, angleRad, getCenter(), getAxis());
|
||||||
cv->popModelViewMatrix();
|
matrix = tmp;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SGRotAnimTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
|
||||||
|
osg::NodeVisitor* nv) const
|
||||||
|
{
|
||||||
|
double angle = 0.0;
|
||||||
|
if (!_condition || _condition->test()) {
|
||||||
|
angle = _animationValue->getValue();
|
||||||
|
_lastAngle = angle;
|
||||||
|
} else {
|
||||||
|
angle = _lastAngle;
|
||||||
|
}
|
||||||
|
double angleRad = SGMiscd::deg2rad(angle);
|
||||||
|
if (_referenceFrame == RELATIVE_RF) {
|
||||||
|
// FIXME optimize
|
||||||
|
osg::Matrix tmp;
|
||||||
|
set_rotation(tmp, -angleRad, getCenter(), getAxis());
|
||||||
|
matrix.postMult(tmp);
|
||||||
|
} else {
|
||||||
|
osg::Matrix tmp;
|
||||||
|
set_rotation(tmp, -angleRad, getCenter(), getAxis());
|
||||||
|
matrix = tmp;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cull callback
|
// Cull callback
|
||||||
@@ -793,7 +779,8 @@ protected:
|
|||||||
// more than one camera. It is probably safe to overwrite the
|
// more than one camera. It is probably safe to overwrite the
|
||||||
// reference values in multiple threads, but we'll provide a
|
// reference values in multiple threads, but we'll provide a
|
||||||
// threadsafe way to manage those values just to be safe.
|
// threadsafe way to manage those values just to be safe.
|
||||||
struct ReferenceValues {
|
struct ReferenceValues : public osg::Referenced
|
||||||
|
{
|
||||||
ReferenceValues(double t, double rot, double vel)
|
ReferenceValues(double t, double rot, double vel)
|
||||||
: _time(t), _rotation(rot), _rotVelocity(vel)
|
: _time(t), _rotation(rot), _rotVelocity(vel)
|
||||||
{
|
{
|
||||||
@@ -815,19 +802,31 @@ void SpinAnimCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
|||||||
if (!_condition || _condition->test()) {
|
if (!_condition || _condition->test()) {
|
||||||
double t = nv->getFrameStamp()->getReferenceTime();
|
double t = nv->getFrameStamp()->getReferenceTime();
|
||||||
double rps = _animationValue->getValue() / 60.0;
|
double rps = _animationValue->getValue() / 60.0;
|
||||||
ReferenceValues* refval = static_cast<ReferenceValues*>(_referenceValues.get());
|
ref_ptr<ReferenceValues>
|
||||||
if (!refval || refval->_rotVelocity != rps) {
|
refval(static_cast<ReferenceValues*>(_referenceValues.get()));
|
||||||
ReferenceValues* newref = 0;
|
if (!refval || refval->_rotVelocity != rps) {
|
||||||
if (!refval) {
|
ref_ptr<ReferenceValues> newref;
|
||||||
|
if (!refval.valid()) {
|
||||||
// initialization
|
// initialization
|
||||||
newref = new ReferenceValues(t, 0.0, rps);
|
newref = new ReferenceValues(t, 0.0, rps);
|
||||||
} else {
|
} else {
|
||||||
double newRot = refval->_rotation + (t - refval->_time) * refval->_rotVelocity;
|
double newRot = refval->_rotation + (t - refval->_time) * refval->_rotVelocity;
|
||||||
newref = new ReferenceValues(t, newRot, rps);
|
newref = new ReferenceValues(t, newRot, rps);
|
||||||
}
|
}
|
||||||
|
// increment reference pointer, because it will be stored
|
||||||
|
// naked in _referenceValues.
|
||||||
|
newref->ref();
|
||||||
if (_referenceValues.assign(newref, refval)) {
|
if (_referenceValues.assign(newref, refval)) {
|
||||||
delete refval;
|
if (refval.valid()) {
|
||||||
|
DeletionManager::instance()->addStaleObject(refval.get());
|
||||||
|
refval->unref();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Another thread installed new values before us
|
||||||
|
newref->unref();
|
||||||
}
|
}
|
||||||
|
// Whatever happened, we can use the reference values just
|
||||||
|
// calculated.
|
||||||
refval = newref;
|
refval = newref;
|
||||||
}
|
}
|
||||||
double rotation = refval->_rotation + (t - refval->_time) * rps;
|
double rotation = refval->_rotation + (t - refval->_time) * rps;
|
||||||
@@ -892,21 +891,28 @@ SGRotateAnimation::SGRotateAnimation(const SGPropertyNode* configNode,
|
|||||||
osg::Group*
|
osg::Group*
|
||||||
SGRotateAnimation::createAnimationGroup(osg::Group& parent)
|
SGRotateAnimation::createAnimationGroup(osg::Group& parent)
|
||||||
{
|
{
|
||||||
SGRotateTransform* transform = new SGRotateTransform;
|
if (_isSpin) {
|
||||||
transform->setName("rotate animation");
|
SGRotateTransform* transform = new SGRotateTransform;
|
||||||
if (_isSpin) {
|
transform->setName("spin rotate animation");
|
||||||
SpinAnimCallback* cc;
|
SpinAnimCallback* cc;
|
||||||
cc = new SpinAnimCallback(_condition, _animationValue, _initialValue);
|
cc = new SpinAnimCallback(_condition, _animationValue, _initialValue);
|
||||||
transform->setCullCallback(cc);
|
transform->setCullCallback(cc);
|
||||||
} else if (_animationValue || !_animationValue->isConst()) {
|
transform->setCenter(_center);
|
||||||
RotAnimCallback* cc = new RotAnimCallback(_condition, _animationValue, _initialValue);
|
transform->setAxis(_axis);
|
||||||
transform->setCullCallback(cc);
|
transform->setAngleDeg(_initialValue);
|
||||||
}
|
parent.addChild(transform);
|
||||||
transform->setCenter(_center);
|
return transform;
|
||||||
transform->setAxis(_axis);
|
} else {
|
||||||
transform->setAngleDeg(_initialValue);
|
SGRotAnimTransform* transform = new SGRotAnimTransform;
|
||||||
parent.addChild(transform);
|
transform->setName("rotate animation");
|
||||||
return transform;
|
transform->_condition = _condition;
|
||||||
|
transform->_animationValue = _animationValue;
|
||||||
|
transform->_lastAngle = _initialValue;
|
||||||
|
transform->setCenter(_center);
|
||||||
|
transform->setAxis(_axis);
|
||||||
|
parent.addChild(transform);
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1956,7 +1962,8 @@ public:
|
|||||||
virtual void transform(osg::Matrix& matrix)
|
virtual void transform(osg::Matrix& matrix)
|
||||||
{
|
{
|
||||||
osg::Matrix tmp;
|
osg::Matrix tmp;
|
||||||
set_rotation(tmp, _value, _center, _axis);
|
SGRotateTransform::set_rotation(tmp, SGMiscd::deg2rad(_value), _center,
|
||||||
|
_axis);
|
||||||
matrix.preMult(tmp);
|
matrix.preMult(tmp);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ include (SimGearComponent)
|
|||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
CopyOp.hxx
|
CopyOp.hxx
|
||||||
|
DeletionManager.hxx
|
||||||
NodeAndDrawableVisitor.hxx
|
NodeAndDrawableVisitor.hxx
|
||||||
Noise.hxx
|
Noise.hxx
|
||||||
OsgMath.hxx
|
OsgMath.hxx
|
||||||
@@ -28,6 +29,7 @@ set(HEADERS
|
|||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
CopyOp.cxx
|
CopyOp.cxx
|
||||||
|
DeletionManager.cxx
|
||||||
NodeAndDrawableVisitor.cxx
|
NodeAndDrawableVisitor.cxx
|
||||||
Noise.cxx
|
Noise.cxx
|
||||||
PrimitiveUtils.cxx
|
PrimitiveUtils.cxx
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// DeletionManager.hxx -- defer deletions to a safe time
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012 Tim Moore timoore33@gmail.com
|
||||||
|
//
|
||||||
|
// 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 Library General Public
|
||||||
|
// License along with this library; if not, write to the
|
||||||
|
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
// Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#include "DeletionManager.hxx"
|
||||||
|
|
||||||
|
#include <OpenThreads/ScopedLock>
|
||||||
|
#include <osg/Node>
|
||||||
|
#include "OsgSingleton.hxx"
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
using namespace osg;
|
||||||
|
|
||||||
|
bool DeletionManager::handle(const osgGA::GUIEventAdapter& ea,
|
||||||
|
osgGA::GUIActionAdapter&,
|
||||||
|
osg::Object*, osg::NodeVisitor*)
|
||||||
|
{
|
||||||
|
if (ea.getEventType() == osgGA::GUIEventAdapter::FRAME)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||||
|
_staleObjects.resize(0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeletionManager::addStaleObject(Referenced* obj)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
|
||||||
|
_staleObjects.push_back(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeletionManager::install(Node* node)
|
||||||
|
{
|
||||||
|
node->addEventCallback(instance());
|
||||||
|
}
|
||||||
|
|
||||||
|
DeletionManager* DeletionManager::instance()
|
||||||
|
{
|
||||||
|
return SingletonRefPtr<DeletionManager>::instance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// DeletionManager.hxx -- defer deletions to a safe time
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012 Tim Moore timoore33@gmail.com
|
||||||
|
//
|
||||||
|
// 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 Library General Public
|
||||||
|
// License along with this library; if not, write to the
|
||||||
|
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
// Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
#ifndef SIMGEAR_DELETIONMANAGER_HXX
|
||||||
|
#define SIMGEAR_DELETIONMANAGER_HXX 1
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
#include <osg/NodeCallback>
|
||||||
|
#include <osg/Referenced>
|
||||||
|
#include <osgGA/GUIEventHandler>
|
||||||
|
|
||||||
|
namespace simgear
|
||||||
|
{
|
||||||
|
class DeletionManager : public osgGA::GUIEventHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool handle(const osgGA::GUIEventAdapter& ea,
|
||||||
|
osgGA::GUIActionAdapter& aa,
|
||||||
|
osg::Object* object, osg::NodeVisitor* nv);
|
||||||
|
void addStaleObject(osg::Referenced* obj);
|
||||||
|
static void install(osg::Node* node);
|
||||||
|
static DeletionManager* instance();
|
||||||
|
protected:
|
||||||
|
OpenThreads::Mutex _mutex;
|
||||||
|
std::vector<osg::ref_ptr<osg::Referenced> > _staleObjects;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user