//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
-#ifndef __cplusplus
+#ifndef __cplusplus
# error This library requires C++
-#endif
+#endif
+
+#include <osgDB/Registry>
+#include <osgDB/Input>
+#include <osgDB/Output>
#include <simgear/compiler.h>
#include <simgear/constants.h>
-#include <plib/sg.h>
-#include <plib/ssg.h>
-
#include "placementtrans.hxx"
-ssgPlacementTransform::ssgPlacementTransform(void)
+#include <simgear/scene/util/SGUpdateVisitor.hxx>
+
+class SGPlacementTransform::UpdateCallback : public osg::NodeCallback {
+public:
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ // short circuit updates if the model we place with that branch
+ // out of sight.
+ // Note that the transform is still correct.
+ SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
+ if (updateVisitor) {
+ SGPlacementTransform* placementTransform;
+ placementTransform = static_cast<SGPlacementTransform*>(node);
+ double dist2 = distSqr(updateVisitor->getGlobalEyePos(),
+ placementTransform->getGlobalPos());
+ if (updateVisitor->getSqrVisibility() < dist2)
+ return;
+ }
+ // note, callback is responsible for scenegraph traversal so
+ // should always include call traverse(node,nv) to ensure
+ // that the rest of cullbacks and the scene graph are traversed.
+ traverse(node, nv);
+ }
+};
+
+
+SGPlacementTransform::SGPlacementTransform(void) :
+ _placement_offset(0, 0, 0),
+ _rotation(1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1)
{
+ setUpdateCallback(new UpdateCallback);
}
-ssgPlacementTransform::~ssgPlacementTransform(void)
+SGPlacementTransform::SGPlacementTransform(const SGPlacementTransform& trans,
+ const osg::CopyOp& copyop):
+ osg::Transform(trans, copyop),
+ _placement_offset(trans._placement_offset),
+ _rotation(trans._rotation)
{
+
}
-ssgBase *ssgPlacementTransform::clone(int clone_flags)
+SGPlacementTransform::~SGPlacementTransform(void)
{
- ssgPlacementTransform *b = new ssgPlacementTransform;
- b->copy_from(this, clone_flags);
- return b;
}
-void
-ssgPlacementTransform::copy_from(ssgPlacementTransform *src, int clone_flags)
+bool
+SGPlacementTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor*) const
{
- ssgBaseTransform::copy_from(src, clone_flags);
- sgdCopyVec3(_placement_offset, src->_placement_offset);
- sgdCopyVec3(_scenery_center, src->_scenery_center);
+ osg::Matrix t;
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ t(j, i) = _rotation(i, j);
+ }
+ t(3, i) = _placement_offset(i);
+ }
+
+ if (_referenceFrame == RELATIVE_RF)
+ matrix.preMult(t);
+ else
+ matrix = t;
+ return true;
}
-void ssgPlacementTransform::setTransform(sgdVec3 off)
+bool
+SGPlacementTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor*) const
{
- sgdCopyVec3(_placement_offset, off);
- sgdVec3 tmp;
- sgdSubVec3(tmp, _placement_offset, _scenery_center);
- sgMat4 tmat;
- sgZeroVec4(tmat[0]);
- tmat[0][0] = 1;
- sgZeroVec4(tmat[1]);
- tmat[1][1] = 1;
- sgZeroVec4(tmat[2]);
- tmat[2][2] = 1;
- sgSetVec3(tmat[3], tmp);
- tmat[3][3] = 1;
- ssgTransform::setTransform(tmat);
+ osg::Matrix t;
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ t(j, i) = _rotation(i, j);
+ }
+ t(3, i) = _placement_offset(i);
+ }
+ t = osg::Matrix::inverse(t);
+
+ if (_referenceFrame == RELATIVE_RF)
+ matrix.postMult(t);
+ else
+ matrix = t;
+ return true;
}
-void ssgPlacementTransform::setTransform(sgdVec3 off, sgMat4 rot)
+// Functions to read / write SGPlacementTrans from / to a .osg file,
+// mostly for debugging purposes.
+
+namespace {
+
+bool PlacementTrans_readLocalData(osg::Object& obj, osgDB::Input& fr)
{
- sgdCopyVec3(_placement_offset, off);
- sgdVec3 tmp;
- sgdSubVec3(tmp, _placement_offset, _scenery_center);
- sgMat4 tmat;
- sgCopyVec4(tmat[0], rot[0]);
- sgCopyVec4(tmat[1], rot[1]);
- sgCopyVec4(tmat[2], rot[2]);
- sgSetVec3(tmat[3], tmp);
- tmat[3][3] = 1;
- ssgTransform::setTransform(tmat);
+ SGPlacementTransform& trans = static_cast<SGPlacementTransform&>(obj);
+ SGMatrixd rotation(1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+ SGVec3d placementOffset(0, 0, 0);
+
+ if (fr[0].matchWord("rotation") && fr[1].isOpenBracket()) {
+ fr += 2;
+ for (int i = 0; i < 3; i++) {
+ SGVec3d scratch;
+ if (!fr.readSequence(scratch.osg()))
+ return false;
+ fr += 3;
+ for (int j = 0; j < 3; j++)
+ rotation(j, i) = scratch[j];
+ }
+ if (fr[0].isCloseBracket())
+ ++fr;
+ else
+ return false;
+ }
+ if (fr[0].matchWord("placement")) {
+ ++fr;
+ if (fr.readSequence(placementOffset.osg()))
+ fr += 3;
+ else
+ return false;
+ }
+ trans.setTransform(placementOffset, rotation);
+ return true;
}
-void ssgPlacementTransform::setSceneryCenter(sgdVec3 xyz)
+bool PlacementTrans_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
{
- sgdCopyVec3(_scenery_center, xyz);
- sgdVec3 tmp;
- sgdSubVec3(tmp, _placement_offset, _scenery_center);
- sgMat4 tmat;
- getTransform(tmat);
- sgSetVec3(tmat[3], tmp);
- ssgTransform::setTransform(tmat);
+ const SGPlacementTransform& trans
+ = static_cast<const SGPlacementTransform&>(obj);
+ const SGMatrixd& rotation = trans.getRotation();
+ const SGVec3d& placement = trans.getGlobalPos();
+
+ fw.indent() << "rotation {" << std::endl;
+ fw.moveIn();
+ for (int i = 0; i < 3; i++) {
+ fw.indent();
+ for (int j = 0; j < 3; j++) {
+ fw << rotation(j, i) << " ";
+ }
+ fw << std::endl;
+ }
+ fw.moveOut();
+ fw.indent() << "}" << std::endl;
+ int prec = fw.precision();
+ fw.precision(15);
+ fw.indent() << "placement ";
+ for (int i = 0; i < 3; i++) {
+ fw << placement(i) << " ";
+ }
+ fw << std::endl;
+ fw.precision(prec);
+ return true;
}
+}
+
+osgDB::RegisterDotOsgWrapperProxy g_SGPlacementTransProxy
+(
+ new SGPlacementTransform,
+ "SGPlacementTransform",
+ "Object Node Transform SGPlacementTransform Group",
+ &PlacementTrans_readLocalData,
+ &PlacementTrans_writeLocalData
+);