From 81f553aaeea541f98b4690e4a267be24235c589a Mon Sep 17 00:00:00 2001 From: Don BURNS Date: Wed, 19 Sep 2001 23:41:39 +0000 Subject: [PATCH] o Updated Metrowerks files for MacOS. They aren't 100% there yet, but getting there. o First cut of osgcluster demo. Very simple beginings. Alas I only one PC here so I can't test it in its current guise. o New support for NodeCallbacks, via AppCallback attached to osg::Node's, and a default osgUtil::AppVisitor which calls them on each frame. o Support for traversal masks in osg::NodeVisitor, osg::Node which allows nodes to be switched on or off via a bit mask. o Suppport for traversal number (frame number) and reference time into osg::NodeVisitor to handle syncronization of app and cull traversals. This also assist clustering as traversal number master to slaves. --- Metrowerks/Metrowerks.mcp | Bin 0 -> 214148 bytes doc/doc++/osg/MatrixProduct.html | 51 +++ doc/doc++/osg/NodeCallback.html | 137 +++++++ doc/doc++/osg/Viewport.html | 203 ++++++++++ doc/doc++/osgUtil/AppVisitor.html | 142 +++++++ include/osg/Matrix.new | 224 +++++++++++ include/osg/Matrix.old | 184 +++++++++ include/osg/NodeCallback | 46 +++ include/osg/Viewport | 63 +++ include/osgUtil/AppVisitor | 67 ++++ src/Demos/osgcluster/Makedepend | 0 src/Demos/osgcluster/Makefile | 25 ++ src/Demos/osgcluster/README | 67 ++++ src/Demos/osgcluster/broadcaster.cpp | 125 ++++++ src/Demos/osgcluster/broadcaster.h | 45 +++ src/Demos/osgcluster/osgcluster.cpp | 350 +++++++++++++++++ src/Demos/osgcluster/receiver.cpp | 104 +++++ src/Demos/osgcluster/receiver.h | 39 ++ src/osg/Matrix.cpp.new | 558 ++++++++++++++++++++++++++ src/osg/Matrix.cpp.old | 568 +++++++++++++++++++++++++++ src/osg/Viewport.cpp | 22 ++ src/osgUtil/AppVisitor.cpp | 18 + 22 files changed, 3038 insertions(+) create mode 100644 Metrowerks/Metrowerks.mcp create mode 100644 doc/doc++/osg/MatrixProduct.html create mode 100644 doc/doc++/osg/NodeCallback.html create mode 100644 doc/doc++/osg/Viewport.html create mode 100644 doc/doc++/osgUtil/AppVisitor.html create mode 100644 include/osg/Matrix.new create mode 100644 include/osg/Matrix.old create mode 100644 include/osg/NodeCallback create mode 100644 include/osg/Viewport create mode 100644 include/osgUtil/AppVisitor create mode 100644 src/Demos/osgcluster/Makedepend create mode 100644 src/Demos/osgcluster/Makefile create mode 100644 src/Demos/osgcluster/README create mode 100644 src/Demos/osgcluster/broadcaster.cpp create mode 100644 src/Demos/osgcluster/broadcaster.h create mode 100644 src/Demos/osgcluster/osgcluster.cpp create mode 100644 src/Demos/osgcluster/receiver.cpp create mode 100644 src/Demos/osgcluster/receiver.h create mode 100644 src/osg/Matrix.cpp.new create mode 100644 src/osg/Matrix.cpp.old create mode 100644 src/osg/Viewport.cpp create mode 100644 src/osgUtil/AppVisitor.cpp diff --git a/Metrowerks/Metrowerks.mcp b/Metrowerks/Metrowerks.mcp new file mode 100644 index 0000000000000000000000000000000000000000..eff0ddd6e264533dd2869dd3fb28c6582eb367b5 GIT binary patch literal 214148 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 + + + + class osg::Matrix::MatrixProduct + + + + +

class MatrixProduct


+ +
+

+

Public Fields

+[more]const Matrix& A +
+[more]const Matrix& B +

+ +

+

Public Methods

+[more] MatrixProduct( const Matrix& lhs, const Matrix& rhs ) +

+ +
+ + +
+

Documentation

+
+ + + +
oconst Matrix& A +

+ + +

oconst Matrix& B +

+ + +

o MatrixProduct( const Matrix& lhs, const Matrix& rhs ) +

+ +
This class has no child classes.
+ +

Alphabetic index HTML hierarchy of classes or Java


+
+This page was generated with the help of DOC++. + + diff --git a/doc/doc++/osg/NodeCallback.html b/doc/doc++/osg/NodeCallback.html new file mode 100644 index 000000000..a5bb99de5 --- /dev/null +++ b/doc/doc++/osg/NodeCallback.html @@ -0,0 +1,137 @@ + + + + + class SG_EXPORT osg::NodeCallback + + + + +

class SG_EXPORT osg::NodeCallback


+ +

Inheritance:

+ + + + + + + +
+ +
+

+

Public Fields

+[more]Requirements _requirements +

+ +

+

Public Methods

+[more] NodeCallback(const Requirements ncr=NO_REQUIREMENTS) +
+[more]virtual ~NodeCallback() +
+[more]inline void setRequirements(const Requirements ncr) +
Set what values from traversal are required by this NodeCallback +
+[more]inline const Requirements getRequirements() const +
Get what values from traversal are required by this NodeCallback +
+[more]virtual void operator()(Node*, NodeVisitor*) +
Callback method call by the NodeVisitor when visiting a node +

+ +

+

Public Members

+[more]enum Requirements +
The range of values which can be accumulated by the NodeVisitor. +

+ +
+

Inherited from Referenced:

+
+

+

Public Methods

+oinline Referenced& operator = (Referenced&) +
+oinline void ref() const +
+oinline void unref() const +
+oinline const int referenceCount() const +

+ +

+

Protected Fields

+omutable int _refCount +

+ +
+ + +
+

Documentation

+
+ + + +
oenum Requirements +
The range of values which can be accumulated by the NodeVisitor. +

+ + + +
o NO_REQUIREMENTS +

+ + +

o REQUIRES_TRAVERSAL +

+ + +

o REQUIRES_PARENT_PATH +

+ + +

o REQUIRES_ACCUMULATED_MATRIX +

+ + +

o REQUIRES_ACCUMULATED_INVERSE +

+ + + +
o NodeCallback(const Requirements ncr=NO_REQUIREMENTS) +

+ + +

ovirtual ~NodeCallback() +

+ + +

oinline void setRequirements(const Requirements ncr) +
Set what values from traversal are required by this NodeCallback +

+ + +

oinline const Requirements getRequirements() const +
Get what values from traversal are required by this NodeCallback +

+ + +

ovirtual void operator()(Node*, NodeVisitor*) +
Callback method call by the NodeVisitor when visiting a node +

+ + +

oRequirements _requirements +

+ +
This class has no child classes.
+ +

Alphabetic index HTML hierarchy of classes or Java


+
+This page was generated with the help of DOC++. + + diff --git a/doc/doc++/osg/Viewport.html b/doc/doc++/osg/Viewport.html new file mode 100644 index 000000000..ed736af69 --- /dev/null +++ b/doc/doc++/osg/Viewport.html @@ -0,0 +1,203 @@ + + + + + class SG_EXPORT osg::Viewport + + + + +

class SG_EXPORT osg::Viewport

Encapsulte OpenGL glViewport
+
+ +

Inheritance:

+ + + + + + + +
+ +
+

+

Public Methods

+[more] Viewport() +
+[more]virtual bool isSameKindAs(const Object* obj) const +
+[more]virtual Object* clone() const +
+[more]virtual const char* className() const +
+[more]virtual const Type getType() const +
+[more]inline void setViewport(const int x, const int y, const int width, const int height) +
+[more]void getViewport(int& x, int& y, int& width, int& height) +
+[more]inline const int x() const +
+[more]inline const int y() const +
+[more]inline const int width() const +
+[more]inline const int height() const +
+[more]inline const float aspectRatio() const +
return the aspcetRatio of the viewport, which is equal to width/height +
+[more]virtual void apply(State& state) const +

+ +

+

Protected Fields

+[more]int _x +
+[more]int _y +
+[more]int _width +
+[more]int _height +

+ +

+

Protected Methods

+[more]virtual ~Viewport() +

+ +
+

Inherited from StateAttribute:

+
+

+

Public Methods

+ovirtual void setStateSetModes(StateSet&, const GLModeValue) const +
+ovirtual void compile(State&) const +

+ +

+

Public Members

+otypedef GLenum GLMode +
+otypedef unsigned int GLModeValue +
+otypedef unsigned int OverrideValue +
+oenum Values +
+oenum Type +

+ +
+

Inherited from Object:

+
+
+

Inherited from Referenced:

+
+

+

Public Methods

+oinline Referenced& operator = (Referenced&) +
+oinline void ref() const +
+oinline void unref() const +
+oinline const int referenceCount() const +

+ +

+

Protected Fields

+omutable int _refCount +

+ +
+ + +
+

Documentation

+
Encapsulte OpenGL glViewport
+
+ + + +
o Viewport() +

+ + +

ovirtual bool isSameKindAs(const Object* obj) const +

+ + +

ovirtual Object* clone() const +

+ + +

ovirtual const char* className() const +

+ + +

ovirtual const Type getType() const +

+ + +

oinline void setViewport(const int x, const int y, const int width, const int height) +

+ + +

ovoid getViewport(int& x, int& y, int& width, int& height) +

+ + +

oinline const int x() const +

+ + +

oinline const int y() const +

+ + +

oinline const int width() const +

+ + +

oinline const int height() const +

+ + +

oinline const float aspectRatio() const +
return the aspcetRatio of the viewport, which is equal to width/height +

+ + +

ovirtual void apply(State& state) const +

+ + +

ovirtual ~Viewport() +

+ + +

oint _x +

+ + +

oint _y +

+ + +

oint _width +

+ + +

oint _height +

+ +
This class has no child classes.
+ +

Alphabetic index HTML hierarchy of classes or Java


+
+This page was generated with the help of DOC++. + + diff --git a/doc/doc++/osgUtil/AppVisitor.html b/doc/doc++/osgUtil/AppVisitor.html new file mode 100644 index 000000000..d001f5c94 --- /dev/null +++ b/doc/doc++/osgUtil/AppVisitor.html @@ -0,0 +1,142 @@ + + + + + class OSGUTIL_EXPORT osgUtil::AppVisitor + + + + +

class OSGUTIL_EXPORT osgUtil::AppVisitor

Basic AppVisitor implementation for animating a scene.
+
+ +

Inheritance:

+ + + + + + + +
+ +
+

+

Public Methods

+[more] AppVisitor() +
+[more]virtual ~AppVisitor() +
+[more]virtual void reset() +
+[more]virtual void apply(osg::Node& node) +
+[more]virtual void apply(osg::Geode& node) +
+[more]virtual void apply(osg::Billboard& node) +
+[more]virtual void apply(osg::LightSource& node) +
+[more]virtual void apply(osg::Group& node) +
+[more]virtual void apply(osg::Transform& node) +
+[more]virtual void apply(osg::Switch& node) +
+[more]virtual void apply(osg::LOD& node) +
+[more]virtual void apply(osg::Impostor& node) +

+ +

+

Protected Methods

+[more] AppVisitor(const AppVisitor&) +
prevent unwanted copy construction +
+[more]AppVisitor& operator = (const AppVisitor&) +
prevent unwanted copy operator +
+[more]inline void handle_callbacks(osg::Node& node) +

+ +
+ + +
+

Documentation

+
+Basic AppVisitor implementation for animating a scene. +This visitor traverses the scene graph, call each nodes appCallback if +it exists.
+
+ + + +
o AppVisitor() +

+ + +

ovirtual ~AppVisitor() +

+ + +

ovirtual void reset() +

+ + +

ovirtual void apply(osg::Node& node) +

+ + +

ovirtual void apply(osg::Geode& node) +

+ + +

ovirtual void apply(osg::Billboard& node) +

+ + +

ovirtual void apply(osg::LightSource& node) +

+ + +

ovirtual void apply(osg::Group& node) +

+ + +

ovirtual void apply(osg::Transform& node) +

+ + +

ovirtual void apply(osg::Switch& node) +

+ + +

ovirtual void apply(osg::LOD& node) +

+ + +

ovirtual void apply(osg::Impostor& node) +

+ + +

o AppVisitor(const AppVisitor&) +
prevent unwanted copy construction +

+ + +

oAppVisitor& operator = (const AppVisitor&) +
prevent unwanted copy operator +

+ + +

oinline void handle_callbacks(osg::Node& node) +

+ +
This class has no child classes.
+ +

Alphabetic index HTML hierarchy of classes or Java


+
+This page was generated with the help of DOC++. + + diff --git a/include/osg/Matrix.new b/include/osg/Matrix.new new file mode 100644 index 000000000..e05ddcc65 --- /dev/null +++ b/include/osg/Matrix.new @@ -0,0 +1,224 @@ + +#ifndef OSG_Matrix +#define OSG_Matrix 1 + +#include +#include +#include +//#include + +#ifdef OSG_USE_IO_DOT_H +#include +#else +#include +using namespace std; +#endif + +#define METAOBJ(name) \ + virtual Object* clone() const { return new name (); } \ + virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } \ + virtual const char* className() const { return #name; } + +namespace osg { + +class Quat; + +class SG_EXPORT Matrix : public Object +{ +// private: + public: + float _mat[4][4]; + bool fully_realized; + + public: +// const char* name() { return "My Matrix "; } + METAOBJ(Matrix) + + Matrix(); + Matrix( const Matrix& other ); + explicit Matrix( float const * const def ); + Matrix( float a00, float a01, float a02, float a03, + float a10, float a11, float a12, float a13, + float a20, float a21, float a22, float a23, + float a30, float a31, float a32, float a33); + + virtual ~Matrix() {} + + Matrix& operator = (const Matrix& ); + + inline float& operator()(int col, int row) { return _mat[col][row]; } + inline float operator()(int col, int row) const { return _mat[col][row]; } + + void set( float const * const ); + void set( float a00, float a01, float a02, float a03, + float a10, float a11, float a12, float a13, + float a20, float a21, float a22, float a23, + float a30, float a31, float a32, float a33); + const float * values() { return (const float *)_mat; } + + void makeIdent(); + void makeScale( const Vec3& ); + void makeScale( float, float, float ); + + void makeTrans( const Vec3& ); + void makeTrans( float, float, float ); + //TODO: original preTrans was optimized (M=Tr*M) + // but also has the assumption that M (this) is an affine transformation Matrix + // can I still do something to optimize the same case now? + + void makeRot( const Vec3& from, const Vec3& to ); + void makeRot( float angle, const Vec3& orientation ); + void makeRot( float angle, float x, float y, float z ); + void makeRot( const Quat& ); + void makeRot( float, float, float ); //Euler angles + + bool invert( const Matrix& ); + bool invertAffine( const Matrix& ); + + //basic utility functions to create new matrices or vectors + static Matrix scale( const Vec3& ); + static Matrix scale( float, float, float ); + static Matrix trans( const Vec3& ); + static Matrix trans( float, float, float ); + static Matrix rotate( const Vec3&, const Vec3& ); + static Matrix rotate( float, float, float, float ); + static Matrix rotate( const Quat& ); + + inline Vec3 preMult( const Vec3& v ) const; + inline Vec3 postMult( const Vec3& v ) const; + inline Vec3 operator* ( const Vec3& v ) const; + inline Vec4 preMult( const Vec4& v ) const; + inline Vec4 postMult( const Vec4& v ) const; + inline Vec4 operator* ( const Vec4& v ) const; + +//start of Deprecated methods + + void copy( const Matrix& ); + void preScale( float sx, float sy, float sz, const Matrix& m ); + void postScale( const Matrix& m, float sx, float sy, float sz ); + void preScale( float sx, float sy, float sz ); + void postScale( float sx, float sy, float sz ); + + void preTrans( float tx, float ty, float tz, const Matrix& m ); + void postTrans( const Matrix& m, float tx, float ty, float tz ); + void preTrans( float tx, float ty, float tz); + void postTrans( float tx, float ty, float tz ); + + void preRot( float deg, float x, float y, float z, const Matrix& m ); + void postRot( const Matrix& m, float deg, float x, float y, float z ); + void preRot( float deg, float x, float y, float z ); + void postRot( float deg, float x, float y, float z ); + + /** apply apply an 3x3 transform of v*M[0..2,0..2] */ + inline static Vec3 transform3x3(const Vec3& v,const Matrix& m); + /** apply apply an 3x3 transform of M[0..2,0..2]*v */ + inline static Vec3 transform3x3(const Matrix& m,const Vec3& v); + +//end of Deprecated methods + + + // basic matrix multiplication, our workhorse methods. + void mult( const Matrix&, const Matrix& ); + void preMult( const Matrix& ); + void postMult( const Matrix& ); + + // Helper class to optimize product expressions somewhat + class MatrixProduct { + public: + const Matrix& A; + const Matrix& B; + + MatrixProduct( const Matrix& lhs, const Matrix& rhs ) : A(lhs), B(rhs) {} + }; + + inline MatrixProduct operator * ( const Matrix& other ) const + { return MatrixProduct(*this, other); } + + inline void operator *= ( const Matrix& other ) + { if( this == &other ) { + Matrix temp(other); + postMult( temp ); + } + else postMult( other ); + } + inline void operator = ( const MatrixProduct& p ) + { + if( this == &(p.A)) postMult(p.B); + else if( this == &(p.B)) preMult(p.A); + else mult( p.A, p.B ); + } + + Matrix( const MatrixProduct& p ) //allows implicit evaluation of the product + { mult( p.A, p.B ); } +}; + +inline Vec3 Matrix::postMult ( const Vec3& v ) const { + float d = 1.0f/(_mat[3][0]*v.x()+_mat[3][1]*v.y()+_mat[3][2]*v.z()+_mat[3][3]) ; + return Vec3( (_mat[0][0]*v.x() + _mat[0][1]*v.y() + _mat[0][2]*v.z() + _mat[0][3])*d, + (_mat[1][0]*v.x() + _mat[1][1]*v.y() + _mat[1][2]*v.z() + _mat[1][3])*d, + (_mat[2][0]*v.x() + _mat[2][1]*v.y() + _mat[2][2]*v.z() + _mat[2][3])*d) ; +} + +inline Vec3 Matrix::preMult (const Vec3& v ) const { + float d = 1.0f/(_mat[0][3]*v.x()+_mat[1][3]*v.y()+_mat[2][3]*v.z()+_mat[3][3]) ; + return Vec3( (_mat[0][0]*v.x() + _mat[1][0]*v.y() + _mat[2][0]*v.z() + _mat[3][0])*d, + (_mat[0][1]*v.x() + _mat[1][1]*v.y() + _mat[2][1]*v.z() + _mat[3][1])*d, + (_mat[0][2]*v.x() + _mat[1][2]*v.y() + _mat[2][2]*v.z() + _mat[3][2])*d); +} +inline Vec3 Matrix::operator* (const Vec3& v) const { + return postMult(v); +} +inline Vec3 operator* (const Vec3& v, const Matrix& m ) { + return m.preMult(v); +} +inline Vec4 Matrix::postMult(const Vec4& v) const { + return Vec4( (_mat[0][0]*v.x() + _mat[0][1]*v.y() + _mat[0][2]*v.z() + _mat[0][3]*v.w()), + (_mat[1][0]*v.x() + _mat[1][1]*v.y() + _mat[1][2]*v.z() + _mat[1][3]*v.w()), + (_mat[2][0]*v.x() + _mat[2][1]*v.y() + _mat[2][2]*v.z() + _mat[2][3]*v.w()), + (_mat[3][0]*v.x() + _mat[3][1]*v.y() + _mat[3][2]*v.z() + _mat[3][3]*v.w())) ; +} +/* +inline Vec4 Matrix::preMult(const Vec4& v,const Matrix& m) { + return Vec4( (m._mat[0][0]*v.x() + m._mat[1][0]*v.y() + m._mat[2][0]*v.z() + m._mat[3][0]*v.w()), + (m._mat[0][1]*v.x() + m._mat[1][1]*v.y() + m._mat[2][1]*v.z() + m._mat[3][1]*v.w()), + (m._mat[0][2]*v.x() + m._mat[1][2]*v.y() + m._mat[2][2]*v.z() + m._mat[3][2]*v.w()), + (m._mat[0][3]*v.x() + m._mat[1][3]*v.y() + m._mat[2][3]*v.z() + m._mat[3][3]*v.w())); +} +*/ +inline Vec4 Matrix::operator* (const Vec4& v) const { + return postMult(v); +} +inline Vec4 operator* (const Vec4& v, const Matrix& m ) { + return m.preMult(v); +} + +inline Vec3 Matrix::transform3x3(const Vec3& v,const Matrix& m) +{ + return Vec3( (m._mat[0][0]*v.x() + m._mat[1][0]*v.y() + m._mat[2][0]*v.z()), + (m._mat[0][1]*v.x() + m._mat[1][1]*v.y() + m._mat[2][1]*v.z()), + (m._mat[0][2]*v.x() + m._mat[1][2]*v.y() + m._mat[2][2]*v.z())); +} + +inline Vec3 Matrix::transform3x3(const Matrix& m,const Vec3& v) +{ + return Vec3( (m._mat[0][0]*v.x() + m._mat[0][1]*v.y() + m._mat[0][2]*v.z()), + (m._mat[1][0]*v.x() + m._mat[1][1]*v.y() + m._mat[1][2]*v.z()), + (m._mat[2][0]*v.x() + m._mat[2][1]*v.y() + m._mat[2][2]*v.z()) ) ; +} + +inline ostream& operator<< (ostream& os, const Matrix& m ) { + os << "{"; + for(int row=0; row<4; ++row) { + os << "\t"; + for(int col=0; col<4; ++col) + os << m(col,row) << " "; + os << endl; + } + os << "}" << endl; + return os; +} + +}; //namespace osg + + +#endif diff --git a/include/osg/Matrix.old b/include/osg/Matrix.old new file mode 100644 index 000000000..0455d431d --- /dev/null +++ b/include/osg/Matrix.old @@ -0,0 +1,184 @@ +#ifndef OSG_MATRIX +#define OSG_MATRIX 1 + +#include +#include +#include + +#ifdef OSG_USE_IO_DOT_H +#include +#else +#include +using namespace std; +#endif + +namespace osg { + +/** 4x4 Matrix for storage & manipulation of transformations in scene graph. + Provides basic maths operations, IO and via osg::Object reference counting. + You can directly load the matrix with OpenGL's LoadMatrixf() function via + the public member _mat as the matrix is stored in the OpenGL format. + Caution: The disadvantage of this feature is, that the matrix access is + 'transposed' if you compare it with the standard C/C++ 2d-array-access + convention . I.e. _mat[i][j] accesses the ith column of the jth row in the + 4x4 matrix. +*/ + +class SG_EXPORT Matrix : public Object +{ + public: + Matrix(); + Matrix(const Matrix& matrix); + Matrix( float a00, float a01, float a02, float a03, + float a10, float a11, float a12, float a13, + float a20, float a21, float a22, float a23, + float a30, float a31, float a32, float a33); + + Matrix& operator = (const Matrix& matrix); + + virtual ~Matrix(); + + virtual Object* clone() const { return new Matrix(); } + virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } + virtual const char* className() const { return "Matrix"; } + + void makeIdent(); + + void set(const float* m); + + void set( float a00, float a01, float a02, float a03, + float a10, float a11, float a12, float a13, + float a20, float a21, float a22, float a23, + float a30, float a31, float a32, float a33); + + void copy(const Matrix& matrix); + + void makeScale(float sx, float sy, float sz); + void preScale( float sx, float sy, float sz, const Matrix& m ); + void postScale( const Matrix& m, float sx, float sy, float sz ); + + void preScale( float sx, float sy, float sz ); + void postScale( float sx, float sy, float sz ); + + + void makeTrans( float tx, float ty, float tz ); + void preTrans( float tx, float ty, float tz, const Matrix& m ); + void postTrans( const Matrix& m, float tx, float ty, float tz ); + + void preTrans( float tx, float ty, float tz ); + void postTrans( float tx, float ty, float tz ); + + + /** + * Calc the rotation matrix which aligns vector \a old_vec with + * vector \a new_vec. Both \a old_vec and \a new_vec must have + * length 1.0. + */ + void makeRot( const Vec3& old_vec, const Vec3& new_vec ); + + void makeRot( float deg, float x, float y, float z ); + void preRot( float deg, float x, float y, float z, const Matrix& m ); + void postRot( const Matrix& m, float deg, float x, float y, float z ); + + void preRot( float deg, float x, float y, float z ); + void postRot( float deg, float x, float y, float z ); + + void setTrans( float tx, float ty, float tz ); + void setTrans( const Vec3& v ); + Vec3 getTrans() const { return Vec3(_mat[3][0],_mat[3][1],_mat[3][2]); } + + void preMult(const Matrix& m); + void postMult(const Matrix& m); + void mult(const Matrix& lhs,const Matrix& rhs); + + Matrix operator * (const Matrix& m) const; + + /** apply apply an 3x3 transform of v*M[0..2,0..2] */ + inline static Vec3 transform3x3(const Vec3& v,const Matrix& m); + /** apply apply an 3x3 transform of M[0..2,0..2]*v */ + inline static Vec3 transform3x3(const Matrix& m,const Vec3& v); + + /** post multipy v. ie. (m*v) */ + inline Vec3 operator * (const Vec3& v) const; + + /** pre multipy v. ie. (v*m) */ + friend inline Vec3 operator * (const Vec3& v,const Matrix& m); + + /** post multipy v. ie. (m*v) */ + inline Vec4 operator * (const Vec4& v) const; + + /** pre multipy v. ie. (v*m) */ + friend inline Vec4 operator * (const Vec4& v,const Matrix& m); + + friend inline ostream& operator << (ostream& output, const Matrix& matrix); + + bool invert(const Matrix& m); + + public : + float _mat[4][4]; + + protected: +}; + +inline Vec3 Matrix::operator * (const Vec3& v) const +{ + float d = 1.0f/(_mat[3][0]*v.x()+_mat[3][1]*v.y()+_mat[3][2]*v.z()+_mat[3][3]) ; + return Vec3( (_mat[0][0]*v.x() + _mat[0][1]*v.y() + _mat[0][2]*v.z() + _mat[0][3])*d, + (_mat[1][0]*v.x() + _mat[1][1]*v.y() + _mat[1][2]*v.z() + _mat[1][3])*d, + (_mat[2][0]*v.x() + _mat[2][1]*v.y() + _mat[2][2]*v.z() + _mat[2][3])*d) ; +} + + +inline Vec3 operator * (const Vec3& v,const Matrix& m) +{ + float d = 1.0f/(m._mat[0][3]*v.x()+m._mat[1][3]*v.y()+m._mat[2][3]*v.z()+m._mat[3][3]) ; + return Vec3( (m._mat[0][0]*v.x() + m._mat[1][0]*v.y() + m._mat[2][0]*v.z() + m._mat[3][0])*d, + (m._mat[0][1]*v.x() + m._mat[1][1]*v.y() + m._mat[2][1]*v.z() + m._mat[3][1])*d, + (m._mat[0][2]*v.x() + m._mat[1][2]*v.y() + m._mat[2][2]*v.z() + m._mat[3][2])*d); +} + +inline Vec4 Matrix::operator * (const Vec4& v) const +{ + return Vec4( (_mat[0][0]*v.x() + _mat[0][1]*v.y() + _mat[0][2]*v.z() + _mat[0][3]*v.w()), + (_mat[1][0]*v.x() + _mat[1][1]*v.y() + _mat[1][2]*v.z() + _mat[1][3]*v.w()), + (_mat[2][0]*v.x() + _mat[2][1]*v.y() + _mat[2][2]*v.z() + _mat[2][3]*v.w()), + (_mat[3][0]*v.x() + _mat[3][1]*v.y() + _mat[3][2]*v.z() + _mat[3][3]*v.w())) ; +} + + +inline Vec4 operator * (const Vec4& v,const Matrix& m) +{ + return Vec4( (m._mat[0][0]*v.x() + m._mat[1][0]*v.y() + m._mat[2][0]*v.z() + m._mat[3][0]*v.w()), + (m._mat[0][1]*v.x() + m._mat[1][1]*v.y() + m._mat[2][1]*v.z() + m._mat[3][1]*v.w()), + (m._mat[0][2]*v.x() + m._mat[1][2]*v.y() + m._mat[2][2]*v.z() + m._mat[3][2]*v.w()), + (m._mat[0][3]*v.x() + m._mat[1][3]*v.y() + m._mat[2][3]*v.z() + m._mat[3][3]*v.w())); +} + +inline Vec3 Matrix::transform3x3(const Vec3& v,const Matrix& m) +{ + return Vec3( (m._mat[0][0]*v.x() + m._mat[1][0]*v.y() + m._mat[2][0]*v.z()), + (m._mat[0][1]*v.x() + m._mat[1][1]*v.y() + m._mat[2][1]*v.z()), + (m._mat[0][2]*v.x() + m._mat[1][2]*v.y() + m._mat[2][2]*v.z())); +} + +inline Vec3 Matrix::transform3x3(const Matrix& m,const Vec3& v) +{ + return Vec3( (m._mat[0][0]*v.x() + m._mat[0][1]*v.y() + m._mat[0][2]*v.z()), + (m._mat[1][0]*v.x() + m._mat[1][1]*v.y() + m._mat[1][2]*v.z()), + (m._mat[2][0]*v.x() + m._mat[2][1]*v.y() + m._mat[2][2]*v.z()) ) ; +} + +inline ostream& operator << (ostream& output, const Matrix& matrix) +{ + output << "{"< + +namespace osg { + +class Node; +class NodeVisitor; + +class SG_EXPORT NodeCallback : public Referenced { + + public : + + /** The range of values which can be accumulated by the NodeVisitor. */ + enum Requirements + { + NO_REQUIREMENTS = 0x0, + REQUIRES_TRAVERSAL = 0x1, + REQUIRES_PARENT_PATH = 0x2, + REQUIRES_ACCUMULATED_MATRIX = 0x4, + REQUIRES_ACCUMULATED_INVERSE = 0x8, + }; + + NodeCallback(const Requirements ncr=NO_REQUIREMENTS):_requirements(ncr) {} + virtual ~NodeCallback() {} + + + /** Set what values from traversal are required by this NodeCallback.*/ + inline void setRequirements(const Requirements ncr) { _requirements=ncr; } + + /** Get what values from traversal are required by this NodeCallback.*/ + inline const Requirements getRequirements() const { return _requirements; } + + /** Callback method call by the NodeVisitor when visiting a node.*/ + virtual void operator()(Node*, NodeVisitor*) {} + + public: + + Requirements _requirements; +}; + +}; // namespace + +#endif + diff --git a/include/osg/Viewport b/include/osg/Viewport new file mode 100644 index 000000000..12a6dd953 --- /dev/null +++ b/include/osg/Viewport @@ -0,0 +1,63 @@ +#ifndef OSG_VIEWPORT +#define OSG_VIEWPORT 1 + +#include +#include +#include + +namespace osg { + +/** Encapsulte OpenGL glViewport. +*/ +class SG_EXPORT Viewport : public StateAttribute +{ + public : + + + Viewport(); + virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=0L; } + virtual Object* clone() const { return new Viewport(); } + virtual const char* className() const { return "Viewport"; } + + virtual const Type getType() const { return VIEWPORT; } + + inline void setViewport(const int x,const int y,const int width,const int height) + { + _x = x; + _y = y; + _width = width; + _height = height; + } + + void getViewport(int& x,int& y,int& width,int& height) + { + x = _x; + y = _y; + width = _width; + height = _height; + } + + inline const int x() const { return _x; } + inline const int y() const { return _y; } + inline const int width() const { return _width; } + inline const int height() const { return _height; } + + /** return the aspcetRatio of the viewport, which is equal to width/height.*/ + inline const float aspectRatio() const { return (float)_width/(float)_height; } + + virtual void apply(State& state) const; + + protected: + + virtual ~Viewport(); + + int _x; + int _y; + int _width; + int _height; + +}; + +}; + +#endif diff --git a/include/osgUtil/AppVisitor b/include/osgUtil/AppVisitor new file mode 100644 index 000000000..36e38e115 --- /dev/null +++ b/include/osgUtil/AppVisitor @@ -0,0 +1,67 @@ +#ifndef OSGUTIL_APPVISITOR +#define OSGUTIL_APPVISITOR 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace osgUtil { + +/** + * Basic AppVisitor implementation for animating a scene. + * This visitor traverses the scene graph, call each nodes appCallback if + * it exists. + */ +class OSGUTIL_EXPORT AppVisitor : public osg::NodeVisitor +{ + public: + + AppVisitor(); + virtual ~AppVisitor(); + + virtual void reset(); + + virtual void apply(osg::Node& node) { handle_callbacks(node); } + + virtual void apply(osg::Geode& node) { handle_callbacks(node); } + virtual void apply(osg::Billboard& node) { handle_callbacks(node); } + virtual void apply(osg::LightSource& node){ handle_callbacks(node); } + + virtual void apply(osg::Group& node) { handle_callbacks(node); } + virtual void apply(osg::Transform& node) { handle_callbacks(node); } + virtual void apply(osg::Switch& node) { handle_callbacks(node); } + virtual void apply(osg::LOD& node) { handle_callbacks(node); } + virtual void apply(osg::Impostor& node) { handle_callbacks(node); } + + + protected: + + /** prevent unwanted copy construction.*/ + AppVisitor(const AppVisitor&):osg::NodeVisitor() {} + + /** prevent unwanted copy operator.*/ + AppVisitor& operator = (const AppVisitor&) { return *this; } + + inline void handle_callbacks(osg::Node& node) + { + osg::NodeCallback* callback = node.getAppCallback(); + if (callback) (*callback)(&node,this); + else if (node.getNumChildrenRequiringAppTraversal()>0) traverse(node); + } + + + +}; + +}; + +#endif + diff --git a/src/Demos/osgcluster/Makedepend b/src/Demos/osgcluster/Makedepend new file mode 100644 index 000000000..e69de29bb diff --git a/src/Demos/osgcluster/Makefile b/src/Demos/osgcluster/Makefile new file mode 100644 index 000000000..0236fafff --- /dev/null +++ b/src/Demos/osgcluster/Makefile @@ -0,0 +1,25 @@ +#!smake +include ../../../Make/makedefs + +C++FILES = \ + broadcaster.cpp\ + receiver.cpp\ + osgcluster.cpp + +C++FLAGS += -g + +TARGET = ../../../bin/osgcluster + +TARGET_BIN_FILES = osgcluster + +#note, use this library list when using the Performer osgPlugin. +#LIBS = ${PFLIBS} -losgGLUT -losgUtil -losgDB -losg $(GLUTLIB) -lGLU -lGL -lm -lXmu -lX11 -lXi + +#note, standard library list. +LIBS = -losgGLUT -losgUtil -losgDB -losg $(GLUTLIB) -lGLU -lGL -lm -lXmu -lX11 -lXi + +C++FLAGS += -I../../../include +LDFLAGS += -L../../../lib + +include ../../../Make/makerules + diff --git a/src/Demos/osgcluster/README b/src/Demos/osgcluster/README new file mode 100644 index 000000000..2d9da8288 --- /dev/null +++ b/src/Demos/osgcluster/README @@ -0,0 +1,67 @@ +osgcluster demonstates basic clustering of machines across a local area +network using UDP packets to send camera position updates from a master viewer +to slave viewers. + +Note, the broadcaster and reciever classes have currently been implement +for Linux/IRIX, hence osgcluster will only work on these systems. It should +also work with little extra work on other Unix based OS's. Support for +WinSocket needs to be added to allow support for Windows. Anybody know +WinSocket enough to tackle this? If so let us know. + +- + +On the master machine run: + + osgcluster -m -f 30 mymodel.osg + + +On the slave machines run: + + for left channel: + + osgcluster -s -f 30 -o 30 mymodel.osg + + for right channel: + + osgcluster -s -f 30 -o 30 mymodel.osg + +The options are : + + -m set to viewer to master so that it broadcasts its camera postion. + -s set to viewer to slave so that it recivers its camera postion. + -n set the socket number to communicate over, defaults to 8100. + -o set offset the slave camera from the master position by specified + number of degress. positive offset turns camera towards right. + -f set the horizontal field of view of the camera. + +Sepetember 2001. +Robert Osfield. + + + +Note: Using sgv with Peformer (for IRIX and Linux users only) +============================================================= + +If you find problems with loading .pfb files its likely that its due to undefined +symbols. This isn't a problem with the OSG implementation, but alas the only +current solution is to directly link you app with the Performer libraries. The +Makefile contains two library list. In Makefile you'll see something like : + + #note, use this library list when using the Performer osgPlugin. + #LIBS = ${PFLIBS} -losgGLUT -losgDB -losg -lGLU -lGL -lm -lXmu -lX11 -lXi + + #note, standard library list. + LIBS = -losgGLUT -losgDB -losg -lGLU -lGL -lm -lXmu -lX11 -lXi + +Simple comment in the LIBS line with PFLIBS and comment out the standard LIBS, +then : + + make clean + make + +Hopefully the Performer distribution will eventually work as a dynamic plugin +but until that day we're stuck with this 'hack'... + + +Robert Osfield, +March 20001. diff --git a/src/Demos/osgcluster/broadcaster.cpp b/src/Demos/osgcluster/broadcaster.cpp new file mode 100644 index 000000000..5a6819d94 --- /dev/null +++ b/src/Demos/osgcluster/broadcaster.cpp @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __linux +#include +#else +#include +#endif + +#include "broadcaster.h" + +#define _VERBOSE 1 + +Broadcaster::Broadcaster( void ) +{ + _port = 0; + _initialized = false; + _buffer = 0L; + _address = 0; +} + +Broadcaster::~Broadcaster( void ) +{ + close( _so ); +} + +bool Broadcaster::init( void ) +{ + if( _port == 0 ) + { + fprintf( stderr, "Broadcaster::init() - port not defined\n" ); + return false; + } + + if( (_so = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) + { + perror( "socket" ); + return false; + } + int on = 1; + setsockopt( _so, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + + saddr.sin_family = AF_INET; + saddr.sin_port = htons( _port ); + if( _address == 0 ) + { + struct ifreq ifr; + setsockopt( _so, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); +#ifdef __linux + strcpy( ifr.ifr_name, "eth0" ); +#else + strcpy( ifr.ifr_name, "ef0" ); +#endif + if( (ioctl( _so, SIOCGIFBRDADDR, &ifr)) < 0 ) + { + perror( "Broadcaster::init() Cannot get Broadcast Address" ); + return false; + } + saddr.sin_addr.s_addr = ( + ((sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr.s_addr); + } + else + { + saddr.sin_addr.s_addr = _address; + } +#ifdef _VERBOSE + unsigned char *ptr = (unsigned char *)&saddr.sin_addr.s_addr; + printf( "Broadcast address : %u.%u.%u.%u\n", ptr[0], ptr[1], ptr[2], ptr[3] ); +#endif + + _initialized = true; + return _initialized; +} + +void Broadcaster::setHost( const char *hostname ) +{ + struct hostent *h; + if( (h = gethostbyname( hostname )) == 0L ) + { + fprintf( stderr, "Broadcaster::setHost() - Cannot resolv an address for \"%s\".\n", hostname ); + _address = 0; + } + else + _address = *(( unsigned long *)h->h_addr); +} + +void Broadcaster::setPort( const short port ) +{ + _port = port; +} + +void Broadcaster::setBuffer( void *buffer, const unsigned int size ) +{ + _buffer = buffer; + _buffer_size = size; +} + +void Broadcaster::sync( void ) +{ + _initialized || init(); + + if( _buffer == 0L ) + { + fprintf( stderr, "Broadcaster::sync() - No buffer\n" ); + return; + } + + unsigned int size = sizeof( struct sockaddr_in ); + sendto( _so, (const void *)_buffer, _buffer_size, + 0, (struct sockaddr *)&saddr, size ); + +} + diff --git a/src/Demos/osgcluster/broadcaster.h b/src/Demos/osgcluster/broadcaster.h new file mode 100644 index 000000000..8475619fa --- /dev/null +++ b/src/Demos/osgcluster/broadcaster.h @@ -0,0 +1,45 @@ +#ifndef __BROADCASTER_H +#define __BROADCASTER_H + +//////////////////////////////////////////////////////////// +// Broadcaster.h +// +// Class definition for broadcasting a buffer to a LAN +// + +#include + +class Broadcaster +{ + public : + + Broadcaster( void ); + ~Broadcaster( void ); + + // Set the broadcast port + void setPort( const short port ); + + // Set the buffer to be broadcast + void setBuffer( void *buffer, const unsigned int buffer_size ); + + // Set a recipient host. If this is used, the Broadcaster + // no longer broadcasts, but rather directs UDP packets at + // host. + void setHost( const char *hostname ); + + // Sync broadcasts the buffer + void sync( void ); + + private : + bool init( void ); + + private : + int _so; + bool _initialized; + short _port; + void *_buffer; + unsigned int _buffer_size; + struct sockaddr_in saddr; + unsigned long _address; +}; +#endif diff --git a/src/Demos/osgcluster/osgcluster.cpp b/src/Demos/osgcluster/osgcluster.cpp new file mode 100644 index 000000000..35b696f99 --- /dev/null +++ b/src/Demos/osgcluster/osgcluster.cpp @@ -0,0 +1,350 @@ +#ifdef USE_MEM_CHECK +#include +#endif + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include "receiver.h" +#include "broadcaster.h" + + +class CameraPacket { + public: + + CameraPacket():_masterKilled(false) {} + + void setPacket(const osg::Camera& camera,int tnum, double rtime) + { + _eye = camera.getEyePoint(); + _center = camera.getCenterPoint(); + _up = camera.getUpVector(); + _traversalNumber = tnum; + _referenceTime = rtime; + } + + void getCamera(osg::Camera& camera,float angle_offset=0.0f) + { + + osg::Vec3 lv = _center-_eye; + osg::Matrix matrix; + matrix.makeIdent(); + matrix.makeRot(angle_offset,_up.x(),_up.y(),_up.z()); + lv = lv*matrix; + + camera.setLookAt(_eye,_eye+lv,_up); + + } + + void getSceneViewUpdate(osgUtil::SceneView& sv) + { + sv.setTraversalNumber(_traversalNumber); + sv.setReferenceTime(_referenceTime); + } + + void setMasterKilled(const bool flag) { _masterKilled = flag; } + const bool getMasterKilled() const { return _masterKilled; } + + bool _masterKilled; + osg::Vec3 _eye; + osg::Vec3 _center; + osg::Vec3 _up; + bool _attachMatrix; + osg::Matrix _matrix; + + int _traversalNumber; + double _referenceTime; + +}; + + +class MySceneView : public osgUtil::SceneView { + + public: + + enum ViewerMode + { + STAND_ALONE, + SLAVE, + MASTER + }; + + MySceneView(ViewerMode viewerMode,int socketNumber,float camera_fov, float camera_offset): + _viewerMode(viewerMode),_socketNumber(socketNumber), + _camera_fov(camera_fov), _camera_offset(camera_offset) + { + setDefaults(); + getCamera()->setAdjustAspectRatioMode(osg::Camera::ADJUST_VERTICAL); + getCamera()->setFOV(camera_fov,camera_fov*(600.0f/800.0f),1.0f,1000.0f); + + _bc.setPort(socketNumber); + _rc.setPort(socketNumber); + }; + + ~MySceneView() + { + if (_viewerMode==MASTER) + { + // need to broadcast my death. + CameraPacket cp; + cp.setPacket(*getCamera(),getTraversalNumber(),getReferenceTime()); + cp.setMasterKilled(true); + + _bc.setBuffer(&cp, sizeof( CameraPacket )); + _bc.sync(); + + cout << "broadcasting death"< NodeList; + NodeList nodeList; + for( i = 1; i < argc; i++ ) + { + + if (argv[i][0]=='-') + { + switch(argv[i][1]) + { + + case('m'): + viewerMode = MySceneView::MASTER; + break; + case('s'): + viewerMode = MySceneView::SLAVE; + break; + case('n'): + ++i; + if (iloadLibrary(argv[i]); + } + break; + case('e'): + ++i; + if (icreateLibraryNameForExt(argv[i]); + osgDB::Registry::instance()->loadLibrary(libName); + } + break; + } + } else + { + osg::Node *node = osgDB::readNodeFile( argv[i] ); + + if( node != (osg::Node *)0L ) + { + if (node->getName().empty()) node->setName( argv[i] ); + nodeList.push_back(node); + } + } + + } + + if (nodeList.size()==0) + { + osg::notify(osg::WARN) << "No data loaded."<1 + { + osg::Group* group = new osg::Group(); + for(NodeList::iterator itr=nodeList.begin(); + itr!=nodeList.end(); + ++itr) + { + group->addChild(*itr); + } + + rootnode = group; + } + + return rootnode; +} + + +int main( int argc, char **argv ) +{ + +#ifdef USE_MEM_CHECK + mtrace(); +#endif + + // initialize the GLUT + glutInit( &argc, argv ); + + if (argc<2) + { + osg::notify(osg::NOTICE)<<"usage:"< mySceneView = new MySceneView(viewerMode,socketNumber,camera_fov,camera_offset); + + mySceneView->setSceneData(rootnode); + + // initialize the viewer. + osgGLUT::Viewer viewer; + viewer.addViewport( mySceneView.get() ); + + // register trackball, flight and drive. + viewer.registerCameraManipulator(new osgUtil::TrackballManipulator); + viewer.registerCameraManipulator(new osgUtil::FlightManipulator); + viewer.registerCameraManipulator(new osgUtil::DriveManipulator); + + viewer.open(); + viewer.run(); + + return 0; +} diff --git a/src/Demos/osgcluster/receiver.cpp b/src/Demos/osgcluster/receiver.cpp new file mode 100644 index 000000000..f24b9162c --- /dev/null +++ b/src/Demos/osgcluster/receiver.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "receiver.h" + +Receiver::Receiver( void ) +{ + _port = 0; + _initialized = false; + _buffer = 0L; +} + +Receiver::~Receiver( void ) +{ + close( _so ); +} + +bool Receiver::init( void ) +{ + if( _port == 0 ) + { + fprintf( stderr, "Receiver::init() - port not defined\n" ); + return false; + } + + if( (_so = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) + { + perror( "socket" ); + return false; + } + int on = 1; + setsockopt( _so, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + + struct sockaddr_in saddr; + saddr.sin_family = AF_INET; + saddr.sin_port = htons( _port ); + saddr.sin_addr.s_addr = 0; + + if( bind( _so, (struct sockaddr *)&saddr, sizeof( saddr )) < 0 ) + { + perror( "bind" ); + return false; + } + + _initialized = true; + return _initialized; +} + + +void Receiver::setPort( const short port ) +{ + _port = port; +} + +void Receiver::setBuffer( void *buffer, const unsigned int size ) +{ + _buffer = buffer; + _buffer_size = size; +} + +void Receiver::sync( void ) +{ + _initialized || init(); + + if( _buffer == 0L ) + { + fprintf( stderr, "Receiver::sync() - No buffer\n" ); + return; + } + +#ifdef __linux + socklen_t +#else + int +#endif + size = sizeof( struct sockaddr_in ); + + fd_set fdset; + FD_ZERO( &fdset ); + FD_SET( _so, &fdset ); + + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + + recvfrom( _so, (caddr_t)_buffer, _buffer_size, 0, 0, &size ); + while( select( _so+1, &fdset, 0L, 0L, &tv ) ) + { + if( FD_ISSET( _so, &fdset ) ) + { + recvfrom( _so, (caddr_t)_buffer, _buffer_size, 0, 0, &size ); + } + } +} + diff --git a/src/Demos/osgcluster/receiver.h b/src/Demos/osgcluster/receiver.h new file mode 100644 index 000000000..20597e6d7 --- /dev/null +++ b/src/Demos/osgcluster/receiver.h @@ -0,0 +1,39 @@ +#ifndef __RECEIVER_H +#define __RECEIVER_H + + +//////////////////////////////////////////////////////////// +// Receiver.h +// +// Class definition for the recipient of a broadcasted message +// + + +class Receiver +{ + public : + + Receiver(); + ~Receiver(); + + // setBuffer defines the buffer into which the broadcasted + // message will be received. + void setBuffer( void *buffer, const unsigned int size ); + + // Define what port to listen and bind to + void setPort( const short port ); + + // Sync does a blocking wait to recieve next message + void sync( void ); + + private : + bool init( void ); + + private : + int _so; + bool _initialized; + short _port; + void *_buffer; + unsigned int _buffer_size; +}; +#endif diff --git a/src/osg/Matrix.cpp.new b/src/osg/Matrix.cpp.new new file mode 100644 index 000000000..0eefc82ca --- /dev/null +++ b/src/osg/Matrix.cpp.new @@ -0,0 +1,558 @@ + +#include +#include +#include + +#include //memcpy +#include //acos + +using namespace osg; + +#define WARN_DEPRECATED + +Matrix::Matrix() : Object(), fully_realized(false) {} + +Matrix::Matrix( const Matrix& other ) : Object() { + set( (float const * const) other._mat ); +} + +Matrix::Matrix( float const * const def ) { + set( def ); +} + +Matrix::Matrix( +float a00, float a01, float a02, float a03, +float a10, float a11, float a12, float a13, +float a20, float a21, float a22, float a23, +float a30, float a31, float a32, float a33) +{ + _mat[0][0] = a00; + _mat[0][1] = a01; + _mat[0][2] = a02; + _mat[0][3] = a03; + + _mat[1][0] = a10; + _mat[1][1] = a11; + _mat[1][2] = a12; + _mat[1][3] = a13; + + _mat[2][0] = a20; + _mat[2][1] = a21; + _mat[2][2] = a22; + _mat[2][3] = a23; + + _mat[3][0] = a30; + _mat[3][1] = a31; + _mat[3][2] = a32; + _mat[3][3] = a33; +} + +Matrix& Matrix::operator = (const Matrix& other ) { + if( &other == this ) return *this; + set((const float*)other._mat); + return *this; +} + +void Matrix::set( float const * const def ) { + memcpy( _mat, def, sizeof(_mat) ); + fully_realized = true; +} + +void Matrix::set( + float a00, float a01, float a02, float a03, + float a10, float a11, float a12, float a13, + float a20, float a21, float a22, float a23, + float a30, float a31, float a32, float a33) +{ + _mat[0][0] = a00; + _mat[0][1] = a01; + _mat[0][2] = a02; + _mat[0][3] = a03; + + _mat[1][0] = a10; + _mat[1][1] = a11; + _mat[1][2] = a12; + _mat[1][3] = a13; + + _mat[2][0] = a20; + _mat[2][1] = a21; + _mat[2][2] = a22; + _mat[2][3] = a23; + + _mat[3][0] = a30; + _mat[3][1] = a31; + _mat[3][2] = a32; + _mat[3][3] = a33; +} + +#define SET_ROW(row, v1, v2, v3, v4 ) \ + _mat[0][(row)] = (v1); \ + _mat[1][(row)] = (v2); \ + _mat[2][(row)] = (v3); \ + _mat[3][(row)] = (v4); + + +void Matrix::makeIdent() { + SET_ROW(0, 1, 0, 0, 0 ) + SET_ROW(1, 0, 1, 0, 0 ) + SET_ROW(2, 0, 0, 1, 0 ) + SET_ROW(3, 0, 0, 0, 1 ) + + fully_realized = true; +} + +void Matrix::makeScale( const Vec3& v ) { + makeScale(v[0], v[1], v[2] ); +} + +void Matrix::makeScale( float x, float y, float z ) { + SET_ROW(0, x, 0, 0, 0 ) + SET_ROW(1, 0, y, 0, 0 ) + SET_ROW(2, 0, 0, z, 0 ) + SET_ROW(3, 0, 0, 0, 1 ) + + fully_realized = true; +} + +void Matrix::makeTrans( const Vec3& v ) { + makeTrans( v[0], v[1], v[2] ); +} + +void Matrix::makeTrans( float x, float y, float z ) { + SET_ROW(0, 1, 0, 0, x ) + SET_ROW(1, 0, 1, 0, y ) + SET_ROW(2, 0, 0, 1, z ) + SET_ROW(3, 0, 0, 0, 1 ) + + fully_realized = true; +} + +void Matrix::makeRot( const Vec3& from, const Vec3& to ) { + double d = from * to; // dot product == cos( angle between from & to ) + if( d < 0.9999 ) { + double angle = acos(d); + Vec3 axis = to ^ from; //we know ((to) x (from)) is perpendicular to both + makeRot( angle, axis ); + } + else + makeIdent(); +} + +void Matrix::makeRot( float angle, const Vec3& axis ) { + makeRot( angle, axis.x(), axis.y(), axis.z() ); +} + +void Matrix::makeRot( float angle, float x, float y, float z ) { + float d = sqrt( x*x + y*y + z*z ); + if( d == 0 ) + return; + + float sin_half = sin( angle/2 ); + float cos_half = cos( angle/2 ); + + Quat q( sin_half * (x/d), + sin_half * (y/d), + sin_half * (z/d), + cos_half ); + makeRot( q ); +} + +void Matrix::makeRot( const Quat& q ) { + // taken from Shoemake/ACM SIGGRAPH 89 + Vec4 v = q.asVec4(); + + double xs = 2 * v.x(); //assume q is already normalized? assert? + double ys = 2 * v.y(); // if not, xs = 2 * v.x() / d, ys = 2 * v.y() / d + double zs = 2 * v.z(); // and zs = 2 * v.z() /d where d = v.length2() + + double xx = xs * v.x(); + double xy = ys * v.x(); + double xz = zs * v.x(); + double yy = ys * v.y(); + double yz = zs * v.y(); + double zz = zs * v.z(); + double wx = xs * v.w(); + double wy = ys * v.w(); + double wz = zs * v.w(); + + SET_ROW(0, 1.0-(yy+zz), xy - wz, xz + wz, 0.0 ) + SET_ROW(1, xy + wz, 1.0-(xx+zz),yz - wx, 0.0 ) + SET_ROW(2, xz - wy, yz + wx, 1.0-(xx+yy),0.0 ) + SET_ROW(3, 0.0, 0.0, 0.0, 1.0 ) + + fully_realized = true; +} + +void Matrix::makeRot( float yaw, float pitch, float roll) { + // lifted straight from SOLID library v1.01 Quaternion.h + // available from http://www.win.tue.nl/~gino/solid/ + // and also distributed under the LGPL + float cosYaw = cos(yaw / 2); + float sinYaw = sin(yaw / 2); + float cosPitch = cos(pitch / 2); + float sinPitch = sin(pitch / 2); + float cosRoll = cos(roll / 2); + float sinRoll = sin(roll / 2); + Quat q(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, + cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, + cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, + cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); + makeRot( q ); +} + +#define INNER_PRODUCT(a,b,c,r) \ + ((a)._mat[0][r] * (b)._mat[c][0]) \ + +((a)._mat[1][r] * (b)._mat[c][1]) \ + +((a)._mat[2][r] * (b)._mat[c][2]) \ + +((a)._mat[3][r] * (b)._mat[c][3]) + +void Matrix::mult( const Matrix& lhs, const Matrix& rhs ) { +// PRECONDITION: We assume neither &lhs nor &rhs == this +// if it did, use preMult or postMult instead + _mat[0][0] = INNER_PRODUCT(lhs, rhs, 0, 0); + _mat[0][1] = INNER_PRODUCT(lhs, rhs, 0, 1); + _mat[0][2] = INNER_PRODUCT(lhs, rhs, 0, 2); + _mat[0][3] = INNER_PRODUCT(lhs, rhs, 0, 3); + _mat[1][0] = INNER_PRODUCT(lhs, rhs, 1, 0); + _mat[1][1] = INNER_PRODUCT(lhs, rhs, 1, 1); + _mat[1][2] = INNER_PRODUCT(lhs, rhs, 1, 2); + _mat[1][3] = INNER_PRODUCT(lhs, rhs, 1, 3); + _mat[2][0] = INNER_PRODUCT(lhs, rhs, 2, 0); + _mat[2][1] = INNER_PRODUCT(lhs, rhs, 2, 1); + _mat[2][2] = INNER_PRODUCT(lhs, rhs, 2, 2); + _mat[2][3] = INNER_PRODUCT(lhs, rhs, 2, 3); + _mat[3][0] = INNER_PRODUCT(lhs, rhs, 3, 0); + _mat[3][1] = INNER_PRODUCT(lhs, rhs, 3, 1); + _mat[3][2] = INNER_PRODUCT(lhs, rhs, 3, 2); + _mat[3][3] = INNER_PRODUCT(lhs, rhs, 3, 3); + fully_realized = true; +} + +void Matrix::preMult( const Matrix& other ) { + float t1,t2,t3,t4; + if( !fully_realized ) { + //act as if this were an identity Matrix + set((const float*)other._mat); + return; + } + for(int col=0; col<4; ++col) { + t1 = INNER_PRODUCT( other, *this, col, 0 ); + t2 = INNER_PRODUCT( other, *this, col, 1 ); + t3 = INNER_PRODUCT( other, *this, col, 2 ); + t4 = INNER_PRODUCT( other, *this, col, 3 ); + _mat[col][0] = t1; + _mat[col][1] = t2; + _mat[col][2] = t3; + _mat[col][3] = t4; + } +} + +void Matrix::postMult( const Matrix& other ) { + float t[4]; + if( !fully_realized ) { + //act as if this were an identity Matrix + set((const float*)other._mat); + return; + } + for(int row=0; row<4; ++row) { + t[0] = INNER_PRODUCT( *this, other, 0, row ); + t[1] = INNER_PRODUCT( *this, other, 1, row ); + t[2] = INNER_PRODUCT( *this, other, 2, row ); + t[3] = INNER_PRODUCT( *this, other, 3, row ); + SET_ROW(row, t[0], t[1], t[2], t[3] ) + } +} + +#undef SET_ROW +#undef INNER_PRODUCT + +bool Matrix::invert( const Matrix& _m ) { + + if (&_m==this) + { + Matrix tm(_m); + return invert(tm); + } + if ( _m._mat[0][3] == 0.0 + && _m._mat[1][3] == 0.0 + && _m._mat[2][3] == 0.0 + && _m._mat[3][3] == 1.0 ) + { + return invertAffine( _m ); + } + + // code lifted from VR Juggler. + // not cleanly added, but seems to work. RO. + const float* a = reinterpret_cast(_m._mat); + float* b = reinterpret_cast(_mat); + + int n = 4; + int i, j, k; + int r[ 4], c[ 4], row[ 4], col[ 4]; + float m[ 4][ 4*2], pivot, max_m, tmp_m, fac; + + /* Initialization */ + for ( i = 0; i < n; i ++ ) + { + r[ i] = c[ i] = 0; + row[ i] = col[ i] = 0; + } + + /* Set working matrix */ + for ( i = 0; i < n; i++ ) + { + for ( j = 0; j < n; j++ ) + { + m[ i][ j] = a[ i * n + j]; + m[ i][ j + n] = ( i == j ) ? 1.0 : 0.0 ; + } + } + + /* Begin of loop */ + for ( k = 0; k < n; k++ ) + { + /* Choosing the pivot */ + for ( i = 0, max_m = 0; i < n; i++ ) + { + if ( row[ i] ) continue; + for ( j = 0; j < n; j++ ) + { + if ( col[ j] ) continue; + tmp_m = fabs( m[ i][j]); + if ( tmp_m > max_m) + { + max_m = tmp_m; + r[ k] = i; + c[ k] = j; + } + } + } + row[ r[k] ] = col[ c[k] ] = 1; + pivot = m[ r[ k] ][ c[ k] ]; + + if ( fabs( pivot) <= 1e-20) + { + notify(WARN) << "*** pivot = %f in mat_inv. ***\n"; + //exit( 0); + return false; + } + + /* Normalization */ + for ( j = 0; j < 2*n; j++ ) + { + if ( j == c[ k] ) + m[ r[ k]][ j] = 1.0; + else + m[ r[ k]][ j] /=pivot; + } + + /* Reduction */ + for ( i = 0; i < n; i++ ) + { + if ( i == r[ k] ) + continue; + + for ( j=0, fac = m[ i][ c[k]];j < 2*n; j++ ) + { + if ( j == c[ k] ) + m[ i][ j] =0.0; + else + m[ i][ j] -=fac * m[ r[k]][ j]; + } + } + } + + /* Assign invers to a matrix */ + for ( i = 0; i < n; i++ ) + for ( j = 0; j < n; j++ ) + row[ i] = ( c[ j] == i ) ? r[j] : row[ i]; + + for ( i = 0; i < n; i++ ) + for ( j = 0; j < n; j++ ) + b[ i * n + j] = m[ row[ i]][j + n]; + + return true; // It worked +} + +const double PRECISION_LIMIT = 1.0e-15; + +bool Matrix::invertAffine( const Matrix& _m ) { + // adapted from Graphics Gems II. + // + // This method treats the matrix as a block matrix and calculates + // the inverse of one submatrix, improving performance over something + // that inverts any non-singular matrix: + // -1 + // -1 [ A 0 ] -1 [ A 0 ] + // M = [ ] = [ -1 ] + // [ C 1 ] [-CA 1 ] + // + // returns true if _m is nonsingular, and (*this) contains its inverse + // otherwise returns false. (*this unchanged) + + // assert (this.isAffine()) ? + double det_1, pos, neg, temp; + + pos = neg = 0.0; + +#define ACCUMULATE \ + { \ + if(temp < 0.0) pos += temp; \ + else neg += temp; \ + } + + temp = _m._mat[0][0] * _m._mat[1][1] * _m._mat[2][2]; ACCUMULATE; + temp = _m._mat[0][1] * _m._mat[1][2] * _m._mat[2][0]; ACCUMULATE; + temp = _m._mat[0][2] * _m._mat[1][0] * _m._mat[2][1]; ACCUMULATE; + + temp = - _m._mat[0][2] * _m._mat[1][1] * _m._mat[2][0]; ACCUMULATE; + temp = - _m._mat[0][1] * _m._mat[1][0] * _m._mat[2][2]; ACCUMULATE; + temp = - _m._mat[0][0] * _m._mat[1][2] * _m._mat[2][1]; ACCUMULATE; + + det_1 = pos + neg; + + if( (det_1 == 0.0) || (abs(det_1/(pos-neg)) < PRECISION_LIMIT )) { + // _m has no inverse + notify(WARN) << "Matrix::invert(): Matrix has no inverse." << endl; + return false; + } + + // inverse is adj(A)/det(A) + det_1 = 1.0 / det_1; + + _mat[0][0] = (_m._mat[1][1] * _m._mat[2][2] - _m._mat[1][2] * _m._mat[2][1]) * det_1; + _mat[1][0] = (_m._mat[1][0] * _m._mat[2][2] - _m._mat[1][2] * _m._mat[2][0]) * det_1; + _mat[2][0] = (_m._mat[1][0] * _m._mat[2][1] - _m._mat[1][1] * _m._mat[2][0]) * det_1; + _mat[0][1] = (_m._mat[0][1] * _m._mat[2][2] - _m._mat[0][2] * _m._mat[2][1]) * det_1; + _mat[1][1] = (_m._mat[0][0] * _m._mat[2][2] - _m._mat[0][2] * _m._mat[2][0]) * det_1; + _mat[2][1] = (_m._mat[0][0] * _m._mat[2][1] - _m._mat[0][1] * _m._mat[2][0]) * det_1; + _mat[0][2] = (_m._mat[0][1] * _m._mat[1][2] - _m._mat[0][2] * _m._mat[1][1]) * det_1; + _mat[1][2] = (_m._mat[0][0] * _m._mat[1][2] - _m._mat[0][2] * _m._mat[1][0]) * det_1; + _mat[2][2] = (_m._mat[0][0] * _m._mat[1][1] - _m._mat[0][1] * _m._mat[1][0]) * det_1; + + // calculate -C * inv(A) + _mat[3][0] = -(_m._mat[3][0] * _mat[0][0] + _m._mat[3][1] * _mat[1][0] + _m._mat[3][2] * _mat[2][0] ); + _mat[3][1] = -(_m._mat[3][0] * _mat[0][1] + _m._mat[3][1] * _mat[1][1] + _m._mat[3][2] * _mat[2][1] ); + _mat[3][2] = -(_m._mat[3][0] * _mat[0][2] + _m._mat[3][1] * _mat[1][2] + _m._mat[3][2] * _mat[2][2] ); + + _mat[0][3] = 0.0; + _mat[1][3] = 0.0; + _mat[2][3] = 0.0; + _mat[3][3] = 1.0; + + fully_realized = true; + return true; +} + +//static utility methods +Matrix Matrix::scale(float sx, float sy, float sz) { + Matrix m; + m.makeScale(sx,sy,sz); + return m; +} +Matrix Matrix::scale(const Vec3& v ) { + return scale(v.x(), v.y(), v.z() ); +} +Matrix Matrix::trans(float tx, float ty, float tz) { + Matrix m; + m.makeTrans(tx,ty,tz); + return m; +} +Matrix Matrix::trans(const Vec3& v ) { + return trans(v.x(), v.y(), v.z() ); +} +Matrix Matrix::rotate( const Quat& q ) { + Matrix m; + m.makeRot( q ); + return m; +} +Matrix Matrix::rotate(float angle, float x, float y, float z ) { + Matrix m; + m.makeRot(angle,x,y,z); + return m; +} +Matrix Matrix::rotate(const Vec3& from, const Vec3& to ) { + Matrix m; + m.makeRot(from,to); + return m; +} + +//Deprecated methods +void Matrix::copy( const Matrix& other) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::copy is deprecated. Use = instead."; +#endif + (*this) = other; +} +void Matrix::preScale( float sx, float sy, float sz, const Matrix& m ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::preScale is deprecated. Use result = (Matrix::scale * m) instead."; + (*this) = ( scale(sx,sy,sz) * m ); +#endif +} +void Matrix::postScale( const Matrix& m, float sx, float sy, float sz ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::postScale is deprecated. Use result = (m * Matrix::scale()) instead."; + (*this) = ( m * scale(sx,sy,sz) ); +#endif +} +void Matrix::preScale( float sx, float sy, float sz ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::preScale is deprecated. Use M.preMult( Matrix::scale ) instead."; + preMult( scale(sx,sy,sz) ); +#endif +} +void Matrix::postScale( float sx, float sy, float sz ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::postScale is deprecated. Use M.postMult( Matrix::scale ) instead."; + postMult( scale(sx,sy,sz) ); +#endif +} +void Matrix::preTrans( float tx, float ty, float tz, const Matrix& m ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::preTrans is deprecated. Use result = Matrix::trans * m instead."; + (*this) = trans(tx,ty,tz) * m; +#endif +} +void Matrix::postTrans( const Matrix& m, float tx, float ty, float tz ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::postTrans is deprecated. Use result = m * Matrix::trans instead."; + (*this) = m * trans(tx,ty,tz); +#endif +} +void Matrix::preTrans( float sx, float sy, float sz ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::preTrans is deprecated. Use result = Matrix::trans * m instead."; + preMult( trans(sx,sy,sz) ); +#endif +} +void Matrix::postTrans( float sx, float sy, float sz ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::postTrans is deprecated. Use result = m * Matrix::trans instead."; + postMult( trans(sx,sy,sz) ); +#endif +} +void Matrix::preRot( float deg, float x, float y, float z, const Matrix& m ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::preRot is deprecated. Use result = Matrix::rot * m instead."; + (*this) = rotate(deg,x,y,z) * m; +#endif +} +void Matrix::postRot( const Matrix& m, float deg, float x, float y, float z ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::postRot is deprecated. Use result = m * Matrix::rotate instead."; + (*this) = m * rotate(deg,x,y,z); +#endif +} +void Matrix::preRot( float deg, float x, float y, float z ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::preRot is deprecated. Use m.preMult( Matrix::rotate ) instead."; + preMult( rotate(deg,x,y,z) ); +#endif +} +void Matrix::postRot( float deg, float x, float y, float z ) { +#ifdef WARN_DEPRECATED + notify(NOTICE) << "Matrix::postRot is deprecated. Use m.postMult( Matrix::rotate ) instead."; + postMult( rotate(deg,x,y,z) ); +#endif +} diff --git a/src/osg/Matrix.cpp.old b/src/osg/Matrix.cpp.old new file mode 100644 index 000000000..d48060776 --- /dev/null +++ b/src/osg/Matrix.cpp.old @@ -0,0 +1,568 @@ +#include +#include + +#include +#include +#include +#include + +#define square(x) ((x)*(x)) +#define DEG2RAD(x) ((x)*M_PI/180.0) +#define RAD2DEG(x) ((x)*180.0/M_PI) + +using namespace osg; + +typedef struct quaternion_ +{ + double x ; + double y ; + double z ; + double w ; +} quaternion ; + +/* C = a(row).b(row) */ + +#define matrix_inner_product( a, b, row, col, C ) \ + { \ + (C)[row][col] = (a)[row][0] * (b)[0][col] + \ + (a)[row][1] * (b)[1][col] + \ + (a)[row][2] * (b)[2][col] + \ + (a)[row][3] * (b)[3][col]; \ + } + +/* C = a.b */ + +#define matrix_mult( a, b, C ) \ + { \ + matrix_inner_product( a, b, 0, 0, C ); \ + matrix_inner_product( a, b, 0, 1, C ); \ + matrix_inner_product( a, b, 0, 2, C ); \ + matrix_inner_product( a, b, 0, 3, C ); \ + matrix_inner_product( a, b, 1, 0, C ); \ + matrix_inner_product( a, b, 1, 1, C ); \ + matrix_inner_product( a, b, 1, 2, C ); \ + matrix_inner_product( a, b, 1, 3, C ); \ + matrix_inner_product( a, b, 2, 0, C ); \ + matrix_inner_product( a, b, 2, 1, C ); \ + matrix_inner_product( a, b, 2, 2, C ); \ + matrix_inner_product( a, b, 2, 3, C ); \ + matrix_inner_product( a, b, 3, 0, C ); \ + matrix_inner_product( a, b, 3, 1, C ); \ + matrix_inner_product( a, b, 3, 2, C ); \ + matrix_inner_product( a, b, 3, 3, C ); \ + } + +static void quaternion_matrix( quaternion *q, double mat[4][4] ) +{ + /* copied from Shoemake/ACM SIGGRAPH 89 */ + double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz ; + + xs = q->x + q->x; + ys = q->y + q->y; + zs = q->z + q->z; + + wx = q->w * xs ; wy = q->w * ys ; wz = q->w * zs ; + xx = q->x * xs ; xy = q->x * ys ; xz = q->x * zs ; + yy = q->y * ys ; yz = q->y * zs ; zz = q->z * zs ; + + mat[0][0] = 1.0 - ( yy + zz ) ; + mat[0][1] = xy - wz ; + mat[0][2] = xz + wy ; + mat[1][0] = xy + wz ; + mat[1][1] = 1.0 - ( xx + zz ) ; + mat[1][2] = yz - wx ; + mat[2][0] = xz - wy ; + mat[2][1] = yz + wx ; + mat[2][2] = 1.0 - ( xx + yy ) ; + + mat[0][3] = 0.0; + mat[1][3] = 0.0; + mat[2][3] = 0.0; + + mat[3][0] = 0.0; + mat[3][1] = 0.0; + mat[3][2] = 0.0; + mat[3][3] = 1.0; +} + + +Matrix::Matrix() +{ + makeIdent(); +} + + +Matrix::Matrix(const Matrix& matrix) : Object() +{ + memcpy(_mat,matrix._mat,sizeof(_mat)); +} + + +Matrix& Matrix::operator = (const Matrix& matrix) +{ + if (&matrix==this) return *this; + memcpy(_mat,matrix._mat,sizeof(_mat)); + return *this; +} + + +Matrix::Matrix( +float a00, float a01, float a02, float a03, +float a10, float a11, float a12, float a13, +float a20, float a21, float a22, float a23, +float a30, float a31, float a32, float a33) +{ + _mat[0][0] = a00; + _mat[0][1] = a01; + _mat[0][2] = a02; + _mat[0][3] = a03; + + _mat[1][0] = a10; + _mat[1][1] = a11; + _mat[1][2] = a12; + _mat[1][3] = a13; + + _mat[2][0] = a20; + _mat[2][1] = a21; + _mat[2][2] = a22; + _mat[2][3] = a23; + + _mat[3][0] = a30; + _mat[3][1] = a31; + _mat[3][2] = a32; + _mat[3][3] = a33; +} + + +Matrix::~Matrix() +{ +} + + +void Matrix::makeIdent() +{ + _mat[0][0] = 1.0f; + _mat[0][1] = 0.0f; + _mat[0][2] = 0.0f; + _mat[0][3] = 0.0f; + + _mat[1][0] = 0.0f; + _mat[1][1] = 1.0f; + _mat[1][2] = 0.0f; + _mat[1][3] = 0.0f; + + _mat[2][0] = 0.0f; + _mat[2][1] = 0.0f; + _mat[2][2] = 1.0f; + _mat[2][3] = 0.0f; + + _mat[3][0] = 0.0f; + _mat[3][1] = 0.0f; + _mat[3][2] = 0.0f; + _mat[3][3] = 1.0f; +} + +void Matrix::set(const float* m) +{ + _mat[0][0] = m[0]; + _mat[0][1] = m[1]; + _mat[0][2] = m[2]; + _mat[0][3] = m[3]; + + _mat[1][0] = m[4]; + _mat[1][1] = m[5]; + _mat[1][2] = m[6]; + _mat[1][3] = m[7]; + + _mat[2][0] = m[8]; + _mat[2][1] = m[9]; + _mat[2][2] = m[10]; + _mat[2][3] = m[11]; + + _mat[3][0] = m[12]; + _mat[3][1] = m[13]; + _mat[3][2] = m[14]; + _mat[3][3] = m[15]; +} + + +void Matrix::set( + float a00, float a01, float a02, float a03, + float a10, float a11, float a12, float a13, + float a20, float a21, float a22, float a23, + float a30, float a31, float a32, float a33) +{ + _mat[0][0] = a00; + _mat[0][1] = a01; + _mat[0][2] = a02; + _mat[0][3] = a03; + + _mat[1][0] = a10; + _mat[1][1] = a11; + _mat[1][2] = a12; + _mat[1][3] = a13; + + _mat[2][0] = a20; + _mat[2][1] = a21; + _mat[2][2] = a22; + _mat[2][3] = a23; + + _mat[3][0] = a30; + _mat[3][1] = a31; + _mat[3][2] = a32; + _mat[3][3] = a33; +} + +void Matrix::copy(const Matrix& matrix) +{ + memcpy(_mat,matrix._mat,sizeof(_mat)); +} + + +void Matrix::makeScale(float sx, float sy, float sz) +{ + makeIdent(); + _mat[0][0] = sx; + _mat[1][1] = sy; + _mat[2][2] = sz; +} + + +void Matrix::preScale( float sx, float sy, float sz, const Matrix& m ) +{ + Matrix transMat; + transMat.makeScale(sx, sy, sz); + mult(transMat,m); +} + + +void Matrix::postScale( const Matrix& m, float sx, float sy, float sz ) +{ + Matrix transMat; + transMat.makeScale(sx, sy, sz); + mult(m,transMat); +} + + +void Matrix::preScale( float sx, float sy, float sz ) +{ + Matrix transMat; + transMat.makeScale(sx, sy, sz); + preMult(transMat); +} + + +void Matrix::postScale( float sx, float sy, float sz ) +{ + Matrix transMat; + transMat.makeScale(sx, sy, sz); + postMult(transMat); +} + + +void Matrix::makeTrans( float tx, float ty, float tz ) +{ + makeIdent(); + _mat[3][0] = tx; + _mat[3][1] = ty; + _mat[3][2] = tz; +} + + +void Matrix::preTrans( float tx, float ty, float tz, const Matrix& m ) +{ + Matrix transMat; + transMat.makeTrans(tx, ty, tz); + mult(transMat,m); +} + + +void Matrix::postTrans( const Matrix& m, float tx, float ty, float tz ) +{ + Matrix transMat; + transMat.makeTrans(tx, ty, tz); + mult(m,transMat); +} + + +void Matrix::preTrans( float tx, float ty, float tz ) +{ + _mat[3][0] = (tx * _mat[0][0]) + (ty * _mat[1][0]) + (tz * _mat[2][0]) + _mat[3][0]; + _mat[3][1] = (tx * _mat[0][1]) + (ty * _mat[1][1]) + (tz * _mat[2][1]) + _mat[3][1]; + _mat[3][2] = (tx * _mat[0][2]) + (ty * _mat[1][2]) + (tz * _mat[2][2]) + _mat[3][2]; + _mat[3][3] = (tx * _mat[0][3]) + (ty * _mat[1][3]) + (tz * _mat[2][3]) + _mat[3][3]; +} + + +void Matrix::postTrans( float tx, float ty, float tz ) +{ + Matrix transMat; + transMat.makeTrans(tx, ty, tz); + postMult(transMat); +} + +void Matrix::makeRot( const Vec3& old_vec, const Vec3& new_vec ) +{ + /* dot product == cos(angle old_vec<>new_vec). */ + double d = new_vec * old_vec; + if ( d < 0.9999 ) + { + double angle = acos( d ); + Vec3 rot_axis = new_vec ^ old_vec; + makeRot( RAD2DEG(angle), + rot_axis.x(), rot_axis.y(), rot_axis.z() ); + } + else + makeIdent(); +} + +void Matrix::makeRot( float deg, float x, float y, float z ) +{ + double __mat[4][4]; + quaternion q; + float d = sqrtf( square(x) + square(y) + square(z) ); + + if( d == 0 ) + return; + + float sin_HalfAngle = sinf( DEG2RAD(deg/2) ); + float cos_HalfAngle = cosf( DEG2RAD(deg/2) ); + + q.x = sin_HalfAngle * (x/d); + q.y = sin_HalfAngle * (y/d); + q.z = sin_HalfAngle * (z/d); + q.w = cos_HalfAngle; + + quaternion_matrix( &q, __mat ); + + for(int i=0;i<4;++i) + { + for(int j=0;j<4;++j) + { + _mat[i][j]=__mat[i][j]; + } + } +} + + +void Matrix::preRot( float deg, float x, float y, float z, const Matrix& m ) +{ + Matrix rotMat; + rotMat.makeRot( deg, x, y, z ); + mult(rotMat,m); +} + + +void Matrix::postRot( const Matrix& m, float deg, float x, float y, float z ) +{ + Matrix rotMat; + rotMat.makeRot( deg, x, y, z ); + mult(m,rotMat); +} + + +void Matrix::preRot( float deg, float x, float y, float z ) +{ + quaternion q; + double __mat[4][4]; + float res_mat[4][4]; + + float d = sqrtf( square(x) + square(y) + square(z) ); + + if( d == 0 ) + return; + + float sin_HalfAngle = sinf( DEG2RAD(deg/2) ); + float cos_HalfAngle = cosf( DEG2RAD(deg/2) ); + + q.x = sin_HalfAngle * (x/d); + q.y = sin_HalfAngle * (y/d); + q.z = sin_HalfAngle * (z/d); + q.w = cos_HalfAngle; + + quaternion_matrix( &q, __mat ); + matrix_mult( __mat, _mat, res_mat ); + memcpy( _mat, res_mat, sizeof( _mat ) ); +} + + +void Matrix::postRot( float deg, float x, float y, float z ) +{ + quaternion q; + double __mat[4][4]; + float res_mat[4][4]; + + float d = sqrtf( square(x) + square(y) + square(z) ); + + if( d == 0 ) + return; + + float sin_HalfAngle = sinf( DEG2RAD(deg/2) ); + float cos_HalfAngle = cosf( DEG2RAD(deg/2) ); + + q.x = sin_HalfAngle * (x/d); + q.y = sin_HalfAngle * (y/d); + q.z = sin_HalfAngle * (z/d); + q.w = cos_HalfAngle; + + quaternion_matrix( &q, __mat ); + matrix_mult( _mat, __mat , res_mat ); + memcpy( _mat, res_mat, sizeof( _mat ) ); +} + + +void Matrix::setTrans( float tx, float ty, float tz ) +{ + _mat[3][0] = tx; + _mat[3][1] = ty; + _mat[3][2] = tz; +} + + +void Matrix::setTrans( const Vec3& v ) +{ + _mat[3][0] = v[0]; + _mat[3][1] = v[1]; + _mat[3][2] = v[2]; +} + + +void Matrix::preMult(const Matrix& m) +{ + Matrix tm; + matrix_mult( m._mat, _mat, tm._mat ); + *this = tm; +} + + +void Matrix::postMult(const Matrix& m) +{ + Matrix tm; + matrix_mult( _mat, m._mat, tm._mat ); + *this = tm; +} + + +void Matrix::mult(const Matrix& lhs,const Matrix& rhs) +{ + if (&lhs==this || &rhs==this) + { + osg::Matrix tm; + matrix_mult( lhs._mat, rhs._mat, tm._mat ); + *this = tm; + } + else + { + matrix_mult( lhs._mat, rhs._mat, _mat ); + } +} + + +Matrix Matrix::operator * (const Matrix& m) const +{ + Matrix tm; + matrix_mult( _mat,m._mat, tm._mat ); + return tm; +} + + +bool Matrix::invert(const Matrix& invm) +{ + if (&invm==this) { + Matrix tm(invm); + return invert(tm); + } + + // code lifted from VR Juggler. + // not cleanly added, but seems to work. RO. + + const float* a = reinterpret_cast(invm._mat); + float* b = reinterpret_cast(_mat); + + int n = 4; + int i, j, k; + int r[ 4], c[ 4], row[ 4], col[ 4]; + float m[ 4][ 4*2], pivot, max_m, tmp_m, fac; + + /* Initialization */ + for ( i = 0; i < n; i ++ ) + { + r[ i] = c[ i] = 0; + row[ i] = col[ i] = 0; + } + + /* Set working matrix */ + for ( i = 0; i < n; i++ ) + { + for ( j = 0; j < n; j++ ) + { + m[ i][ j] = a[ i * n + j]; + m[ i][ j + n] = ( i == j ) ? 1.0 : 0.0 ; + } + } + + /* Begin of loop */ + for ( k = 0; k < n; k++ ) + { + /* Choosing the pivot */ + for ( i = 0, max_m = 0; i < n; i++ ) + { + if ( row[ i] ) continue; + for ( j = 0; j < n; j++ ) + { + if ( col[ j] ) continue; + tmp_m = fabs( m[ i][j]); + if ( tmp_m > max_m) + { + max_m = tmp_m; + r[ k] = i; + c[ k] = j; + } + } + } + row[ r[k] ] = col[ c[k] ] = 1; + pivot = m[ r[ k] ][ c[ k] ]; + + if ( fabs( pivot) <= 1e-20) + { + notify(WARN) << "*** pivot = %f in mat_inv. ***\n"; + //exit( 0); + return false; + } + + /* Normalization */ + for ( j = 0; j < 2*n; j++ ) + { + if ( j == c[ k] ) + m[ r[ k]][ j] = 1.0; + else + m[ r[ k]][ j] /=pivot; + } + + /* Reduction */ + for ( i = 0; i < n; i++ ) + { + if ( i == r[ k] ) + continue; + + for ( j=0, fac = m[ i][ c[k]];j < 2*n; j++ ) + { + if ( j == c[ k] ) + m[ i][ j] =0.0; + else + m[ i][ j] -=fac * m[ r[k]][ j]; + } + } + } + + /* Assign invers to a matrix */ + for ( i = 0; i < n; i++ ) + for ( j = 0; j < n; j++ ) + row[ i] = ( c[ j] == i ) ? r[j] : row[ i]; + + for ( i = 0; i < n; i++ ) + for ( j = 0; j < n; j++ ) + b[ i * n + j] = m[ row[ i]][j + n]; + + return true; // It worked +} diff --git a/src/osg/Viewport.cpp b/src/osg/Viewport.cpp new file mode 100644 index 000000000..5bd5672de --- /dev/null +++ b/src/osg/Viewport.cpp @@ -0,0 +1,22 @@ +#include + +using namespace osg; + +Viewport::Viewport() +{ + _x = 0; + _y = 0; + _width = 800; + _height = 600; +} + + +Viewport::~Viewport() +{ +} + +void Viewport::apply(State&) const +{ + glViewport(_x,_y,_width,_height); +} + diff --git a/src/osgUtil/AppVisitor.cpp b/src/osgUtil/AppVisitor.cpp new file mode 100644 index 000000000..a11665a0c --- /dev/null +++ b/src/osgUtil/AppVisitor.cpp @@ -0,0 +1,18 @@ +#include + +using namespace osg; +using namespace osgUtil; + +AppVisitor::AppVisitor():NodeVisitor(TRAVERSE_ACTIVE_CHILDREN) +{ +} + + +AppVisitor::~AppVisitor() +{ +} + + +void AppVisitor::reset() +{ +}