_viewport;
LightingMode _lightingMode;
bool _prioritizeTextures;
- int _frameNumber;
};
};
diff --git a/include/osgUtil/Tesselator b/include/osgUtil/Tesselator
index 6093feba7..c0fb05a78 100644
--- a/include/osgUtil/Tesselator
+++ b/include/osgUtil/Tesselator
@@ -44,6 +44,8 @@ class OSGUTIL_EXPORT Tesselator
struct VertexIndexSet
{
+ VertexIndexSet() {}
+
VertexIndexSet(Tesselator* tess,const osg::Vec3& vec,osg::uint index)
{
set(tess,vec,index);
diff --git a/include/osgUtil/VisualsRequirementsVisitor b/include/osgUtil/VisualsRequirementsVisitor
index 3a9ce34c9..a6846327c 100644
--- a/include/osgUtil/VisualsRequirementsVisitor
+++ b/include/osgUtil/VisualsRequirementsVisitor
@@ -39,16 +39,16 @@ class OSGUTIL_EXPORT VisualsRequirementsVisitor : public osg::NodeVisitor
const bool requiresDepthBuffer() const { return _requiresDepthBuffer; }
- void setMinumumNumAlphaBits(const unsigned int bits) { _minimumNumberAlphaBits = bits; }
+ void setMinimumNumAlphaBits(const unsigned int bits) { _minimumNumberAlphaBits = bits; }
- const unsigned int getMinumumNumAlphaBits() const { return _minimumNumberAlphaBits; }
+ const unsigned int getMinimumNumAlphaBits() const { return _minimumNumberAlphaBits; }
const bool requiresAlphaBuffer() const { return _minimumNumberAlphaBits!=0; }
- void setMinumumNumStencilBits(const unsigned int bits) { _minimumNumberStencilBits = bits; }
+ void setMinimumNumStencilBits(const unsigned int bits) { _minimumNumberStencilBits = bits; }
- const unsigned int getMinumumNumStencilBits() const { return _minimumNumberStencilBits; }
+ const unsigned int getMinimumNumStencilBits() const { return _minimumNumberStencilBits; }
const bool requiresStencilBuffer() const { return _minimumNumberStencilBits!=0; }
diff --git a/index.html b/index.html
index e6f5bdca7..c67d010fd 100644
--- a/index.html
+++ b/index.html
@@ -8,7 +8,7 @@
Installation Contents
-of Distribution Documentation Plugin
+of Distribution Documentation Plugin
Dependencies Data Sources
Contacts
The Open Scene Graph (OSG) is an Open Source (LGPL), Standard C++, OpenGL
diff --git a/src/Demos/Makefile b/src/Demos/Makefile
index c900c2b63..871b5c577 100644
--- a/src/Demos/Makefile
+++ b/src/Demos/Makefile
@@ -1,7 +1,7 @@
#!smake
SHELL=/bin/sh
-DIRS = sgv osgconv osgcube osgreflect osgtexture osgimpostor osgviews hangglide
+DIRS = sgv osgconv osgcube osgreflect osgtexture osgimpostor osgviews hangglide osgcluster
all :
for f in $(DIRS) ; do cd $$f; $(MAKE) || exit 1; cd ..; done
diff --git a/src/Demos/osgcluster/osgcluster.cpp b/src/Demos/osgcluster/osgcluster.cpp
index 35b696f99..5df3bf763 100644
--- a/src/Demos/osgcluster/osgcluster.cpp
+++ b/src/Demos/osgcluster/osgcluster.cpp
@@ -26,13 +26,15 @@ class CameraPacket {
CameraPacket():_masterKilled(false) {}
- void setPacket(const osg::Camera& camera,int tnum, double rtime)
+ void setPacket(const osg::Camera& camera,const osg::FrameStamp* frameStamp)
{
_eye = camera.getEyePoint();
_center = camera.getCenterPoint();
_up = camera.getUpVector();
- _traversalNumber = tnum;
- _referenceTime = rtime;
+ if (frameStamp)
+ {
+ _frameStamp = *frameStamp;
+ }
}
void getCamera(osg::Camera& camera,float angle_offset=0.0f)
@@ -50,8 +52,9 @@ class CameraPacket {
void getSceneViewUpdate(osgUtil::SceneView& sv)
{
- sv.setTraversalNumber(_traversalNumber);
- sv.setReferenceTime(_referenceTime);
+ // note pass a seperate reference counted FrameStamp
+ // rather than this frame stamp as it can get overwritten.
+ sv.setFrameStamp(new osg::FrameStamp(_frameStamp));
}
void setMasterKilled(const bool flag) { _masterKilled = flag; }
@@ -63,9 +66,12 @@ class CameraPacket {
osg::Vec3 _up;
bool _attachMatrix;
osg::Matrix _matrix;
-
- int _traversalNumber;
- double _referenceTime;
+
+ // note don't use a ref_ptr as used elsewhere for FrameStamp
+ // since we don't want to copy the pointer - but the memory.
+ // FrameStamp doesn't have a private destructor to allow
+ // us to do this, even though its a reference counted object.
+ osg::FrameStamp _frameStamp;
};
@@ -99,7 +105,7 @@ class MySceneView : public osgUtil::SceneView {
{
// need to broadcast my death.
CameraPacket cp;
- cp.setPacket(*getCamera(),getTraversalNumber(),getReferenceTime());
+ cp.setPacket(*getCamera(),getFrameStamp());
cp.setMasterKilled(true);
_bc.setBuffer(&cp, sizeof( CameraPacket ));
@@ -119,7 +125,7 @@ class MySceneView : public osgUtil::SceneView {
case(MASTER):
{
CameraPacket cp;
- cp.setPacket(*getCamera(),getTraversalNumber(),getReferenceTime());
+ cp.setPacket(*getCamera(),getFrameStamp());
_bc.setBuffer(&cp, sizeof( CameraPacket ));
_bc.sync();
diff --git a/src/Demos/osgcube/osgcube.cpp b/src/Demos/osgcube/osgcube.cpp
index ade9fba5a..9987d7948 100644
--- a/src/Demos/osgcube/osgcube.cpp
+++ b/src/Demos/osgcube/osgcube.cpp
@@ -1,11 +1,4 @@
// simple animation demo written by Graeme Harkness.
-// note from Robert to Robert. The animiation techinque
-// present here using glut timer callbacks is one
-// approach, other approaches will soon be supported
-// within the osg itself via an app cullback which
-// can be attached to nodes themselves. This later
-// method will be the prefered approach (have a look
-// at osgreflect's app visitor for a clue.)
#include
@@ -25,48 +18,60 @@
// ----------------------------------------------------------------------
// Global variables - this is basically the stuff which will be animated
// ----------------------------------------------------------------------
-osg::Transform* myTransform;
-osg::GeoSet* cube;
-int mytime=0; // in milliseconds
-unsigned int dt=50; // in milliseconds
-double omega=0.002; // in inverse milliseconds
+class TransformCallback : public osg::NodeCallback{
-// ----------------------------------------------------------------
-// This is the callback function registered with GLUT to be called
-// at a future time in the GLUT loop
-// ----------------------------------------------------------------
-void timedCB( int delta_t )
-{
+ public:
- static float lastdx = 0;
- static float lastdy = 0;
- static float lastdz = 0;
+ TransformCallback(osg::Transform* node,float angularVelocity)
+ {
+ _nodeToOperateOn = node;
+ _angular_velocity = angularVelocity;
+ _previousTraversalNumber = -1;
+ _orig_t = _timer.tick();
+ }
- mytime+=dt;
+ virtual void operator() (osg::Node* node, osg::NodeVisitor* nv)
+ {
+ if (nv)
+ {
+ if (_nodeToOperateOn && node==_nodeToOperateOn)
+ {
+ // ensure that we do not operate on this node more than
+ // once during this traversal. This is an issue since node
+ // can be shared between multiple parents.
+ if (nv->getTraversalNumber()!=_previousTraversalNumber)
+ {
+ osg::Timer_t new_t = _timer.tick();
+ float delta_angle = _angular_velocity*_timer.delta_s(_orig_t,new_t);
+
+ osg::Matrix matrix;
+ matrix.makeRot(delta_angle,1.0f,1.0f,1.0f);
+ matrix.postTrans(1.0f,0.0f,0.0f);
+ matrix.postRot(delta_angle,0.0f,0.0f,1.0f);
+
+ _nodeToOperateOn->setMatrix(matrix);
- // ---------------------------------------------------------
- // Update the Transform so that the cube will appear to oscillate
- // ---------------------------------------------------------
- double dx = 0.5 * cos( (double) omega * (double) mytime );
- double dy = 0.5 * sin( (double) omega * (double) mytime );
- double dz = 0.0;
- myTransform->preTranslate( -lastdx, -lastdy, -lastdz );
- myTransform->preTranslate( (float) dx, (float) dy, dz );
- lastdx=dx; lastdy=dy; lastdz=dz;
+ _previousTraversalNumber = nv->getTraversalNumber();
+ }
+ }
+ }
+
+ // must continue subgraph traversal.
+ nv->traverse(*node);
+
+ }
+
+ protected:
+
+ osg::Transform* _nodeToOperateOn;
+ float _angular_velocity;
- // Graeme, commeted out this call as the cube itself remains static.
- // cube->dirtyDisplayList();
-
- // -------------------------------------------
- // If required, reschedule the timed callback
- // -------------------------------------------
- if ( delta_t != 0 )
- {
- glutTimerFunc( (unsigned int) delta_t, timedCB, delta_t );
- }
-}
+ int _previousTraversalNumber;
+ osg::Timer _timer;
+ osg::Timer_t _orig_t;
+};
osg::Geode* createCube()
{
@@ -75,7 +80,7 @@ osg::Geode* createCube()
// -------------------------------------------
// Set up a new GeoSet which will be our cube
// -------------------------------------------
- cube = new osg::GeoSet();
+ osg::GeoSet* cube = new osg::GeoSet();
// set up the primitives
cube->setPrimType( osg::GeoSet::POLYGON );
@@ -145,10 +150,7 @@ osg::Geode* createCube()
osg::StateSet* cubeState = new osg::StateSet();
osg::Material* redMaterial = new osg::Material();
osg::Vec4 red( 1.0f, 0.0f, 0.0f, 1.0f );
- redMaterial->setEmission( osg::Material::FRONT_AND_BACK, red );
- redMaterial->setAmbient( osg::Material::FRONT_AND_BACK, red );
redMaterial->setDiffuse( osg::Material::FRONT_AND_BACK, red );
- redMaterial->setSpecular( osg::Material::FRONT_AND_BACK, red );
cubeState->setAttribute( redMaterial );
cube->setStateSet( cubeState );
@@ -164,23 +166,19 @@ int main( int argc, char **argv )
glutInit( &argc, argv );
- myTransform = new osg::Transform();
+ osg::Transform* myTransform = new osg::Transform();
myTransform->addChild( createCube() );
+
+ // move node in a circle at 90 degrees a sec.
+ myTransform->setAppCallback(new TransformCallback(myTransform,90.0f));
- // ---------------------------------------------------------------------
- // Register a timer callback with GLUT, in the first instance as a test
- // This will call the function "timedCB(value)" after dt ms
- // I have decided to use value as the time for the next scheduling
- // If the last parameter=0 then don't reschedule the timer.
- // ---------------------------------------------------------------------
- glutTimerFunc( dt, timedCB, dt );
-
+ // create the viewer and the model to it.
osgGLUT::Viewer viewer;
viewer.addViewport( myTransform );
- // register trackball, flight and drive.
+ // register trackball maniupulators.
viewer.registerCameraManipulator(new osgUtil::TrackballManipulator);
-
+
viewer.open();
viewer.run();
diff --git a/src/Demos/osgreflect/osgreflect.cpp b/src/Demos/osgreflect/osgreflect.cpp
index 8c3a4b6a7..a2d65afdd 100644
--- a/src/Demos/osgreflect/osgreflect.cpp
+++ b/src/Demos/osgreflect/osgreflect.cpp
@@ -41,55 +41,64 @@
// we apply them.
-// create an app visitor, to be used on each frame update,
-// the below app visitor rotates the loaded model.
-class AppVisitor : public osg::NodeVisitor {
+class TransformCallback : public osg::NodeCallback{
+
public:
- bool _haveDoneTransformTransform;
- float _delta_angle;
- float _angular_velocity;
- osg::Vec3 _pivotPoint;
- osg::Transform* _modifyTransform;
- osg::Timer _timer;
- osg::Timer_t _previous_t;
-
- AppVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
+ TransformCallback(osg::Transform* node,float angularVelocity)
{
- _haveDoneTransformTransform = true;
- _modifyTransform = NULL;
- _delta_angle = 0;
- _angular_velocity = 45; //degrees a sec.
+ _nodeToOperateOn = node;
+ if (node)
+ {
+ _pivotPoint = node->getBound().center();
+ }
+
+ _angular_velocity = angularVelocity;
+ _previousTraversalNumber = -1;
_previous_t = _timer.tick();
}
- virtual void reset()
+ virtual void operator() (osg::Node* node, osg::NodeVisitor* nv)
{
- // set to no transform done so far in this new traversal.
- _haveDoneTransformTransform = false;
-
- // update angle of rotation.
- osg::Timer_t new_t = _timer.tick();
- _delta_angle = _angular_velocity*_timer.delta_s(_previous_t,new_t);
- _previous_t = new_t;
-
- }
-
- virtual void apply(osg::Transform& visitor_dcs)
- {
-
- if (&visitor_dcs == _modifyTransform && !_haveDoneTransformTransform)
+ if (nv)
{
- // update the specified dcs.
- visitor_dcs.preTranslate(_pivotPoint[0],_pivotPoint[1],_pivotPoint[2]);
- visitor_dcs.preRotate(_delta_angle,0.0f,0.0f,1.0f);
- visitor_dcs.preTranslate(-_pivotPoint[0],-_pivotPoint[1],-_pivotPoint[2]);
+ if (_nodeToOperateOn && node==_nodeToOperateOn)
+ {
+ // ensure that we do not operate on this node more than
+ // once during this traversal. This is an issue since node
+ // can be shared between multiple parents.
+ if (nv->getTraversalNumber()!=_previousTraversalNumber)
+ {
+ osg::Timer_t new_t = _timer.tick();
+ float delta_angle = _angular_velocity*_timer.delta_s(_previous_t,new_t);
+ _previous_t = new_t;
- // set to true to prevent applying rotation more than once
- // since the subgraph appears twice in the overall scene.
- _haveDoneTransformTransform = true;
+ // update the specified dcs.
+ _nodeToOperateOn->preTranslate(_pivotPoint[0],_pivotPoint[1],_pivotPoint[2]);
+ _nodeToOperateOn->preRotate(delta_angle,0.0f,0.0f,1.0f);
+ _nodeToOperateOn->preTranslate(-_pivotPoint[0],-_pivotPoint[1],-_pivotPoint[2]);
+
+ _previousTraversalNumber = nv->getTraversalNumber();
+ }
+ }
}
+
+ // must continue subgraph traversal.
+ nv->traverse(*node);
+
+
}
+
+ protected:
+
+ osg::Transform* _nodeToOperateOn;
+ float _angular_velocity;
+ osg::Vec3 _pivotPoint;
+
+ int _previousTraversalNumber;
+ osg::Timer _timer;
+ osg::Timer_t _previous_t;
+
};
/*
@@ -463,13 +472,7 @@ int main( int argc, char **argv )
osgGLUT::Viewer viewer;
viewer.addViewport( rootNode );
-
- // create and register the app visitor.
- AppVisitor* appVisitor = new AppVisitor();
- appVisitor->_modifyTransform = loadedModelTransform;
- appVisitor->_pivotPoint = bs.center();
-
- viewer.getViewportSceneView(0)->setAppVisitor(appVisitor);
+ loadedModelTransform->setAppCallback(new TransformCallback(loadedModelTransform,45.0f));
// register trackball, flight and drive.
viewer.registerCameraManipulator(new osgUtil::TrackballManipulator);
diff --git a/src/Demos/sgv/sgv.cpp b/src/Demos/sgv/sgv.cpp
index 4b330aef7..06cbd3f9e 100644
--- a/src/Demos/sgv/sgv.cpp
+++ b/src/Demos/sgv/sgv.cpp
@@ -15,7 +15,8 @@
#include
#include
-#include
+#include
+
/*
* Function to read several files (typically one) as specified on the command
@@ -130,6 +131,18 @@ int main( int argc, char **argv )
osg::Timer_t after_load = timer.tick();
cout << "Time for load = "<accept(osv);
+ osv.optimize();
+ #endif
+
+
+
// initialize the viewer.
osgGLUT::Viewer viewer;
viewer.addViewport( rootnode );
diff --git a/src/osg/Billboard.cpp b/src/osg/Billboard.cpp
index 160095fd3..f7f289c8e 100644
--- a/src/osg/Billboard.cpp
+++ b/src/osg/Billboard.cpp
@@ -82,6 +82,7 @@ void Billboard::calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix
float ev_length = ev.length();
if (ev_length>0.0f)
{
+ mat.makeIdent();
//float rotation_zrotation_z = atan2f(ev.x(),ev.y());
//mat.makeRot(rotation_z*180.0f/M_PI,0.0f,0.0f,1.0f);
float inv = 1.0f/ev_length;
diff --git a/src/osg/Camera.cpp b/src/osg/Camera.cpp
index e78081fb5..a95efc658 100644
--- a/src/osg/Camera.cpp
+++ b/src/osg/Camera.cpp
@@ -11,6 +11,8 @@ using namespace osg;
Camera::Camera()
{
+ _adjustAspectRatioMode = ADJUST_HORIZONTAL;
+
// projection details.
setPerspective(60,1.0,1.0,1000.0);
@@ -117,6 +119,34 @@ void Camera::setPerspective(const double fovy,const double aspectRatio,
_dirty = true;
}
+/** Set a sysmetical perspective projection using field of view.*/
+void Camera::setFOV(const double fovx,const double fovy,
+ const double zNear, const double zFar)
+{
+ _projectionType = PERSPECTIVE;
+
+ // note, in Frustum/Perspective mode these values are scaled
+ // by the zNear from when they were initialised to ensure that
+ // subsequent changes in zNear do not affect them.
+
+ // calculate the appropriate left, right etc.
+ double tan_fovx = tan(DEG2RAD(fovx*0.5));
+ double tan_fovy = tan(DEG2RAD(fovy*0.5));
+ _right = tan_fovx;
+ _left = -_right;
+ _top = tan_fovy;
+ _bottom = -_top;
+
+ _zNear = zNear;
+ _zFar = zFar;
+
+ notify(INFO)<<"osg::Camera::setFOV(fovx="<
#include "osg/Geode"
-#include
-
-#ifdef __sgi
-using std::find;
-using std::for_each;
-#endif
-
#define square(x) ((x)*(x))
using namespace osg;
diff --git a/src/osg/Group.cpp b/src/osg/Group.cpp
index 23e83f2ba..85f1169c9 100644
--- a/src/osg/Group.cpp
+++ b/src/osg/Group.cpp
@@ -5,12 +5,6 @@
#include
-// #ifdef __sgi
-// using std::find;
-// using std::for_each;
-// using std::string;
-// #endif
-
#define square(x) ((x)*(x))
using namespace osg;
@@ -58,6 +52,16 @@ bool Group::addChild( Node *child )
dirtyBound();
+ // could now require app traversal thanks to the new subgraph,
+ // so need to check and update if required.
+ if (child->getNumChildrenRequiringAppTraversal()>0 ||
+ child->getAppCallback())
+ {
+ setNumChildrenRequiringAppTraversal(
+ getNumChildrenRequiringAppTraversal()+1
+ );
+ }
+
return true;
}
else return false;
@@ -73,10 +77,23 @@ bool Group::removeChild( Node *child )
ParentList::iterator pitr = std::find(child->_parents.begin(),child->_parents.end(),this);
if (pitr!=child->_parents.end()) child->_parents.erase(pitr);
+ // could now require app traversal thanks to the new subgraph,
+ // so need to check and update if required.
+ // note, need to do this checking before the erase of the child
+ // otherwise child will be invalid.
+ if (child->getNumChildrenRequiringAppTraversal()>0 ||
+ child->getAppCallback())
+ {
+ setNumChildrenRequiringAppTraversal(
+ getNumChildrenRequiringAppTraversal()-1
+ );
+ }
+
// note ref_ptr<> automatically handles decrementing child's reference count.
_children.erase(itr);
dirtyBound();
+
return true;
}
else return false;
diff --git a/src/osg/ImpostorSprite.cpp b/src/osg/ImpostorSprite.cpp
index d5ba472d3..b88e5ae82 100644
--- a/src/osg/ImpostorSprite.cpp
+++ b/src/osg/ImpostorSprite.cpp
@@ -41,7 +41,7 @@ ImpostorSprite::~ImpostorSprite()
}
}
-const float ImpostorSprite::calcPixelError(const Camera& camera,const int* viewport,const osg::Matrix* matrix) const
+const float ImpostorSprite::calcPixelError(const Camera& camera,const Viewport& viewport,const osg::Matrix* matrix) const
{
// find the maximum screen space pixel error between the control coords and the quad coners.
float max_error_sqrd = 0.0f;
@@ -139,6 +139,12 @@ void ImpostorSprite::setTexture(Texture* tex,int s,int t)
ImpostorSpriteManager::ImpostorSpriteManager()
{
+ _texenv = new TexEnv;
+ _texenv->setMode(TexEnv::REPLACE);
+
+ _alphafunc = new osg::AlphaFunc;
+ _alphafunc->setFunction( AlphaFunc::GREATER, 0.000f );
+
_first = NULL;
_last = NULL;
}
@@ -250,8 +256,12 @@ ImpostorSprite* ImpostorSpriteManager::createOrReuseImpostorSprite(int s,int t,i
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
Texture* texture = new Texture;
- stateset->setAttributeAndModes(texture,StateAttribute::ON);
+ stateset->setAttributeAndModes(texture,StateAttribute::ON);
+ stateset->setAttributeAndModes( _alphafunc.get(), StateAttribute::ON );
+ stateset->setAttribute(_texenv.get());
+
+/*
TexEnv* texenv = new TexEnv;
texenv->setMode(TexEnv::REPLACE);
stateset->setAttribute(texenv);
@@ -259,6 +269,8 @@ ImpostorSprite* ImpostorSpriteManager::createOrReuseImpostorSprite(int s,int t,i
AlphaFunc* alphafunc = new osg::AlphaFunc;
alphafunc->setFunction( AlphaFunc::GREATER, 0.000f );
stateset->setAttributeAndModes( alphafunc, StateAttribute::ON );
+*/
+
// stateset->setMode( GL_ALPHA_TEST, StateAttribute::OFF );
diff --git a/src/osg/Makefile b/src/osg/Makefile
index 965d3979b..d8c236d80 100644
--- a/src/osg/Makefile
+++ b/src/osg/Makefile
@@ -13,6 +13,7 @@ C++FILES = \
Depth.cpp \
Drawable.cpp\
Fog.cpp\
+ FrameStamp.cpp\
FrontFace.cpp\
Geode.cpp\
GeoSet.cpp\
@@ -48,6 +49,7 @@ C++FILES = \
Transform.cpp\
Transparency.cpp\
Version.cpp\
+ Viewport.cpp\
TARGET_BASENAME = osg
@@ -69,6 +71,7 @@ TARGET_INCLUDE_FILES = \
osg/Drawable\
osg/Export\
osg/Fog\
+ osg/FrameStamp\
osg/FrontFace\
osg/GL\
osg/GLExtensions\
@@ -86,6 +89,7 @@ TARGET_INCLUDE_FILES = \
osg/Matrix\
osg/MemoryAdapter\
osg/Node\
+ osg/NodeCallback\
osg/NodeVisitor\
osg/Notify\
osg/Object\
@@ -112,6 +116,7 @@ TARGET_INCLUDE_FILES = \
osg/Vec3\
osg/Vec4\
osg/Version\
+ osg/Viewport\
osg/mem_ptr\
osg/ref_ptr\
diff --git a/src/osg/Matrix.cpp b/src/osg/Matrix.cpp
index d48060776..87e98c22b 100644
--- a/src/osg/Matrix.cpp
+++ b/src/osg/Matrix.cpp
@@ -1,418 +1,90 @@
-#include
-#include
-
-#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)
+#include //memcpy
+#include //acos
using namespace osg;
-typedef struct quaternion_
+
+#define DEG2RAD(x) ((x)*M_PI/180.0)
+#define RAD2DEG(x) ((x)*180.0/M_PI)
+
+
+//#define WARN_DEPRECATED
+#define ANGLES_IN_DEGREES
+
+#define SET_ROW(row, v1, v2, v3, v4 ) \
+ _mat[(row)][0] = (v1); \
+ _mat[(row)][1] = (v2); \
+ _mat[(row)][2] = (v3); \
+ _mat[(row)][3] = (v4);
+
+#define INNER_PRODUCT(a,b,r,c) \
+ ((a)._mat[r][0] * (b)._mat[0][c]) \
+ +((a)._mat[r][1] * (b)._mat[1][c]) \
+ +((a)._mat[r][2] * (b)._mat[2][c]) \
+ +((a)._mat[r][3] * (b)._mat[3][c])
+
+
+Matrix::Matrix() : Object(), fully_realized(false) {}
+
+Matrix::Matrix( const Matrix& other ) : Object()
{
- double x ;
- double y ;
- double z ;
- double w ;
-} quaternion ;
+ set( (float const * const) other._mat );
+}
-/* C = a(row).b(row) */
+Matrix::Matrix( float const * const def )
+{
+ set( def );
+}
-#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] )
+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)
{
- /* copied from Shoemake/ACM SIGGRAPH 89 */
- double xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz ;
+ SET_ROW(0, a00, a01, a02, a03 )
+ SET_ROW(1, a10, a11, a12, a13 )
+ SET_ROW(2, a20, a21, a22, a23 )
+ SET_ROW(3, a30, a31, a32, a33 )
- 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;
+ fully_realized = true;
}
-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));
+Matrix& Matrix::operator = (const Matrix& other ) {
+ if( &other == this ) return *this;
+ set((const float*)other._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;
+void Matrix::set( float const * const def ) {
+ memcpy( _mat, def, sizeof(_mat) );
+ fully_realized = true;
}
-Matrix::~Matrix()
+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)
{
+ SET_ROW(0, a00, a01, a02, a03 )
+ SET_ROW(1, a10, a11, a12, a13 )
+ SET_ROW(2, a20, a21, a22, a23 )
+ SET_ROW(3, a30, a31, a32, a33 )
+
+ fully_realized = true;
}
-
-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 )
{
+#ifdef WARN_DEPRECATED
+ notify(NOTICE) << "Matrix::setTrans is deprecated.";
+#endif
_mat[3][0] = tx;
_mat[3][1] = ty;
_mat[3][2] = tz;
@@ -421,62 +93,238 @@ void Matrix::setTrans( float tx, float ty, float tz )
void Matrix::setTrans( const Vec3& v )
{
+#ifdef WARN_DEPRECATED
+ notify(NOTICE) << "Matrix::setTrans is deprecated.";
+#endif
_mat[3][0] = v[0];
_mat[3][1] = v[1];
_mat[3][2] = v[2];
}
-
-void Matrix::preMult(const Matrix& m)
+void Matrix::makeIdent()
{
- Matrix tm;
- matrix_mult( m._mat, _mat, tm._mat );
- *this = tm;
+ 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::postMult(const Matrix& m)
+void Matrix::makeScale( const Vec3& v )
{
- Matrix tm;
- matrix_mult( _mat, m._mat, tm._mat );
- *this = tm;
+ makeScale(v[0], v[1], v[2] );
}
-
-void Matrix::mult(const Matrix& lhs,const Matrix& rhs)
+void Matrix::makeScale( float x, float y, float z )
{
- if (&lhs==this || &rhs==this)
- {
- osg::Matrix tm;
- matrix_mult( lhs._mat, rhs._mat, tm._mat );
- *this = tm;
+ 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, 0 )
+ SET_ROW(1, 0, 1, 0, 0 )
+ SET_ROW(2, 0, 0, 1, 0 )
+ SET_ROW(3, x, y, z, 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);
+#ifdef ANGLES_IN_DEGREES
+ angle = RAD2DEG(angle);
+#endif
+ 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;
+
+#ifdef ANGLES_IN_DEGREES
+ angle = DEG2RAD(angle);
+#endif
+
+ 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 );//NOTE: original used a private quaternion made of doubles
+ makeRot( q ); // but Quat stores the values in a Vec4 made of floats.
+}
+
+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 + wy, 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)
+{
+#ifdef ANGLES_IN_DEGREES
+ yaw = DEG2RAD(yaw);
+ pitch = DEG2RAD(pitch);
+ roll = DEG2RAD(roll);
+#endif
+
+ // 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 );
+}
+
+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 )
+{
+ if( !fully_realized ) {
+ //act as if this were an identity Matrix
+ set((const float*)other._mat);
+ return;
}
- else
+
+ // brute force method requiring a copy
+ //Matrix tmp(other* *this);
+ // *this = tmp;
+
+ // more efficient method just use a float[4] for temporary storage.
+ float t[4];
+ for(int col=0; col<4; ++col) {
+ t[0] = INNER_PRODUCT( other, *this, 0, col );
+ t[1] = INNER_PRODUCT( other, *this, 1, col );
+ t[2] = INNER_PRODUCT( other, *this, 2, col );
+ t[3] = INNER_PRODUCT( other, *this, 3, col );
+ _mat[0][col] = t[0];
+ _mat[1][col] = t[1];
+ _mat[2][col] = t[2];
+ _mat[3][col] = t[3];
+ }
+
+}
+
+void Matrix::postMult( const Matrix& other )
+{
+ if( !fully_realized ) {
+ //act as if this were an identity Matrix
+ set((const float*)other._mat);
+ return;
+ }
+ // brute force method requiring a copy
+ //Matrix tmp(*this * other);
+ // *this = tmp;
+
+ // more efficient method just use a float[4] for temporary storage.
+ float t[4];
+ for(int row=0; row<4; ++row)
{
- matrix_mult( lhs._mat, rhs._mat, _mat );
+ t[0] = INNER_PRODUCT( *this, other, row, 0 );
+ t[1] = INNER_PRODUCT( *this, other, row, 1 );
+ t[2] = INNER_PRODUCT( *this, other, row, 2 );
+ t[3] = INNER_PRODUCT( *this, other, row, 3 );
+ SET_ROW(row, t[0], t[1], t[2], t[3] )
}
}
+#undef SET_ROW
+#undef INNER_PRODUCT
-Matrix Matrix::operator * (const Matrix& m) const
+bool Matrix::invert( const Matrix& _m )
{
- Matrix tm;
- matrix_mult( _mat,m._mat, tm._mat );
- return tm;
-}
-
-bool Matrix::invert(const Matrix& invm)
-{
- if (&invm==this) {
- Matrix tm(invm);
+ 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(invm._mat);
+ const float* a = reinterpret_cast(_m._mat);
float* b = reinterpret_cast(_mat);
int n = 4;
@@ -491,7 +339,7 @@ bool Matrix::invert(const Matrix& invm)
row[ i] = col[ i] = 0;
}
- /* Set working matrix */
+ /* Set working Matrix */
for ( i = 0; i < n; i++ )
{
for ( j = 0; j < n; j++ )
@@ -555,7 +403,7 @@ bool Matrix::invert(const Matrix& invm)
}
}
- /* Assign invers to a matrix */
+ /* 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];
@@ -566,3 +414,154 @@ bool Matrix::invert(const Matrix& invm)
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;
+}
+
+//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.";
+#endif
+ (*this) = ( scale(sx,sy,sz) * m );
+}
+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.";
+#endif
+ (*this) = ( m * scale(sx,sy,sz) );
+}
+void Matrix::preScale( float sx, float sy, float sz ) {
+#ifdef WARN_DEPRECATED
+ notify(NOTICE) << "Matrix::preScale is deprecated. Use M.preMult( Matrix::scale ) instead.";
+#endif
+ preMult( scale(sx,sy,sz) );
+}
+void Matrix::postScale( float sx, float sy, float sz ) {
+#ifdef WARN_DEPRECATED
+ notify(NOTICE) << "Matrix::postScale is deprecated. Use M.postMult( Matrix::scale ) instead.";
+#endif
+ postMult( scale(sx,sy,sz) );
+}
+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.";
+#endif
+ (*this) = trans(tx,ty,tz) * m;
+}
+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.";
+#endif
+ (*this) = m * trans(tx,ty,tz);
+}
+void Matrix::preTrans( float tx, float ty, float tz ) {
+#ifdef WARN_DEPRECATED
+ notify(NOTICE) << "Matrix::preTrans is deprecated. Use result = Matrix::trans * m instead.";
+#endif
+ preMult( trans(tx,ty,tz) );
+}
+void Matrix::postTrans( float sx, float sy, float sz ) {
+#ifdef WARN_DEPRECATED
+ notify(NOTICE) << "Matrix::postTrans is deprecated. Use result = m * Matrix::trans instead.";
+#endif
+ postMult( trans(sx,sy,sz) );
+}
+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.";
+#endif
+ (*this) = rotate(deg,x,y,z) * m;
+}
+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.";
+#endif
+ (*this) = m * rotate(deg,x,y,z);
+}
+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.";
+#endif
+ preMult( rotate(deg,x,y,z) );
+}
+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.";
+#endif
+ postMult( rotate(deg,x,y,z) );
+}
diff --git a/src/osg/Matrix.cpp.new b/src/osg/Matrix.cpp.new
index 0eefc82ca..542a26e81 100644
--- a/src/osg/Matrix.cpp.new
+++ b/src/osg/Matrix.cpp.new
@@ -8,7 +8,12 @@
using namespace osg;
+#define DEG2RAD(x) ((x)*M_PI/180.0)
+#define RAD2DEG(x) ((x)*180.0/M_PI)
+
+
#define WARN_DEPRECATED
+#define ANGLES_IN_DEGREES
Matrix::Matrix() : Object(), fully_realized(false) {}
@@ -86,11 +91,10 @@ void Matrix::set(
}
#define SET_ROW(row, v1, v2, v3, v4 ) \
- _mat[0][(row)] = (v1); \
- _mat[1][(row)] = (v2); \
- _mat[2][(row)] = (v3); \
- _mat[3][(row)] = (v4);
-
+ _mat[(row)][0] = (v1); \
+ _mat[(row)][1] = (v2); \
+ _mat[(row)][2] = (v3); \
+ _mat[(row)][3] = (v4);
void Matrix::makeIdent() {
SET_ROW(0, 1, 0, 0, 0 )
@@ -119,10 +123,10 @@ void Matrix::makeTrans( const Vec3& v ) {
}
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 )
+ SET_ROW(0, 1, 0, 0, 0 )
+ SET_ROW(1, 0, 1, 0, 0 )
+ SET_ROW(2, 0, 0, 1, 0 )
+ SET_ROW(3, x, y, z, 1 )
fully_realized = true;
}
@@ -131,6 +135,9 @@ 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);
+#ifdef ANGLES_IN_DEGREES
+ angle = RAD2DEG(angle);
+#endif
Vec3 axis = to ^ from; //we know ((to) x (from)) is perpendicular to both
makeRot( angle, axis );
}
@@ -138,7 +145,8 @@ void Matrix::makeRot( const Vec3& from, const Vec3& to ) {
makeIdent();
}
-void Matrix::makeRot( float angle, const Vec3& axis ) {
+void Matrix::makeRot( float angle, const Vec3& axis )
+{
makeRot( angle, axis.x(), axis.y(), axis.z() );
}
@@ -147,6 +155,10 @@ void Matrix::makeRot( float angle, float x, float y, float z ) {
if( d == 0 )
return;
+#ifdef ANGLES_IN_DEGREES
+ angle = DEG2RAD(angle);
+#endif
+
float sin_half = sin( angle/2 );
float cos_half = cos( angle/2 );
@@ -175,15 +187,22 @@ void Matrix::makeRot( const Quat& q ) {
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(0, 1.0-(yy+zz), xy + wz, xz - wy, 0.0 )
+ SET_ROW(1, xy - wz, 1.0-(xx+zz),yz + wx, 0.0 )
+ SET_ROW(2, xz + wz, 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) {
+void Matrix::makeRot( float yaw, float pitch, float roll)
+{
+#ifdef ANGLES_IN_DEGREES
+ yaw = DEG2RAD(yaw);
+ pitch = DEG2RAD(pitch);
+ roll = DEG2RAD(roll);
+#endif
+
// lifted straight from SOLID library v1.01 Quaternion.h
// available from http://www.win.tue.nl/~gino/solid/
// and also distributed under the LGPL
@@ -200,11 +219,11 @@ void Matrix::makeRot( float yaw, float pitch, float roll) {
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])
+#define INNER_PRODUCT(a,b,r,c) \
+ ((a)._mat[r][0] * (b)._mat[0][c]) \
+ +((a)._mat[r][1] * (b)._mat[1][c]) \
+ +((a)._mat[r][2] * (b)._mat[2][c]) \
+ +((a)._mat[r][3] * (b)._mat[3][c])
void Matrix::mult( const Matrix& lhs, const Matrix& rhs ) {
// PRECONDITION: We assume neither &lhs nor &rhs == this
@@ -390,7 +409,7 @@ bool Matrix::invertAffine( const Matrix& _m ) {
// returns true if _m is nonsingular, and (*this) contains its inverse
// otherwise returns false. (*this unchanged)
- // assert (this.isAffine()) ?
+ // assert( this->isAffine())?
double det_1, pos, neg, temp;
pos = neg = 0.0;
@@ -487,72 +506,72 @@ void Matrix::copy( const Matrix& 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
+ (*this) = ( scale(sx,sy,sz) * m );
}
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
+ (*this) = ( m * scale(sx,sy,sz) );
}
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
+ preMult( scale(sx,sy,sz) );
}
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
+ postMult( scale(sx,sy,sz) );
}
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
+ (*this) = trans(tx,ty,tz) * m;
}
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
+ (*this) = m * trans(tx,ty,tz);
}
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
+ preMult( trans(sx,sy,sz) );
}
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
+ postMult( trans(sx,sy,sz) );
}
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
+ (*this) = rotate(deg,x,y,z) * m;
}
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
+ (*this) = m * rotate(deg,x,y,z);
}
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
+ preMult( rotate(deg,x,y,z) );
}
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
+ postMult( rotate(deg,x,y,z) );
}
diff --git a/src/osg/Node.cpp b/src/osg/Node.cpp
index 01a0519d7..c65470c13 100644
--- a/src/osg/Node.cpp
+++ b/src/osg/Node.cpp
@@ -13,6 +13,8 @@ Node::Node()
_bsphere_computed = false;
_userData = NULL;
_nodeMask = 0xffffffff;
+
+ _numChildrenRequiringAppTraversal = 0;
}
@@ -24,7 +26,7 @@ Node::~Node()
void Node::accept(NodeVisitor& nv)
{
- nv.apply(*this);
+ if (nv.validNodeMask(*this)) nv.apply(*this);
}
@@ -33,6 +35,83 @@ void Node::ascend(NodeVisitor& nv)
std::for_each(_parents.begin(),_parents.end(),NodeAcceptOp(nv));
}
+void Node::setAppCallback(NodeCallback* nc)
+{
+ // if no changes just return.
+ if (_appCallback==nc) return;
+
+ // app callback has been changed, will need to update
+ // both _appCallback and possibly the numChildrenRequiringAppTraversal
+ // if the number of callbacks changes.
+
+
+ // update the parents numChildrenRequiringAppTraversal
+ // note, if _numChildrenRequiringAppTraversal!=0 then the
+ // parents won't be affected by any app callback change,
+ // so no need to inform them.
+ if (_numChildrenRequiringAppTraversal==0 && !_parents.empty())
+ {
+ int delta = 0;
+ if (_appCallback.valid()) --delta;
+ if (nc) ++delta;
+ if (delta!=0)
+ {
+ // the number of callbacks has changed, need to pass this
+ // on to parents so they know whether app traversal is
+ // reqired on this subgraph.
+ for(ParentList::iterator itr =_parents.begin();
+ itr != _parents.end();
+ ++itr)
+ {
+ (*itr)->setNumChildrenRequiringAppTraversal(
+ (*itr)->getNumChildrenRequiringAppTraversal()+delta );
+ }
+
+ }
+ }
+
+ // set the app callback itself.
+ _appCallback = nc;
+
+}
+
+void Node::setNumChildrenRequiringAppTraversal(const int num)
+{
+ // if no changes just return.
+ if (_numChildrenRequiringAppTraversal==num) return;
+
+ // note, if _appCallback is set then the
+ // parents won't be affected by any changes to
+ // _numChildrenRequiringAppTraversal so no need to inform them.
+ if (!_appCallback && !_parents.empty())
+ {
+
+ // need to pass on changes to parents.
+ int delta = 0;
+ if (_numChildrenRequiringAppTraversal>0) --delta;
+ if (num>0) ++delta;
+ if (delta!=0)
+ {
+ // the number of callbacks has changed, need to pass this
+ // on to parents so they know whether app traversal is
+ // reqired on this subgraph.
+ for(ParentList::iterator itr =_parents.begin();
+ itr != _parents.end();
+ ++itr)
+ {
+ (*itr)->setNumChildrenRequiringAppTraversal(
+ (*itr)->getNumChildrenRequiringAppTraversal()+delta
+ );
+ }
+
+ }
+ }
+
+ // finally update this objects value.
+ _numChildrenRequiringAppTraversal=num;
+
+}
+
const bool Node::computeBound() const
{
_bsphere.init();
diff --git a/src/osg/NodeVisitor.cpp b/src/osg/NodeVisitor.cpp
index 72b87a3ae..9134d71cb 100644
--- a/src/osg/NodeVisitor.cpp
+++ b/src/osg/NodeVisitor.cpp
@@ -5,8 +5,12 @@ using namespace osg;
NodeVisitor::NodeVisitor(TraversalMode tm)
{
+ _traversalNumber = -1;
+
_traversalVisitor = NULL;
_traversalMode = tm;
+ _traversalMask = 0xffffffff;
+ _nodeMaskOverride = 0x0;
}
diff --git a/src/osg/Point.cpp b/src/osg/Point.cpp
index 0d212f253..88341c035 100644
--- a/src/osg/Point.cpp
+++ b/src/osg/Point.cpp
@@ -1,10 +1,6 @@
// Ideas and code borrowed from GLUT pointburst demo
// written by Mark J. Kilgard
-#ifdef WIN32
-#include
-#endif
-
#include "osg/GL"
#include "osg/GLExtensions"
#include "osg/Point"
diff --git a/src/osg/State.cpp b/src/osg/State.cpp
index 5ae95cb4f..3a14e7d56 100644
--- a/src/osg/State.cpp
+++ b/src/osg/State.cpp
@@ -8,7 +8,6 @@ using namespace osg;
State::State()
{
_contextID = 0;
- _frameNumber = 0;
_fineGrainedErrorDetection = true;
}
diff --git a/src/osg/StateSet.cpp b/src/osg/StateSet.cpp
index 807ab719f..0fe6077f2 100644
--- a/src/osg/StateSet.cpp
+++ b/src/osg/StateSet.cpp
@@ -155,31 +155,6 @@ void StateSet::compile(State& state) const
}
}
-
-const StateSet::ModeVector StateSet::getModeVector() const
-{
- ModeVector vec;
- for (ModeList::const_iterator itr = _modeList.begin();
- itr!=_modeList.end();
- ++itr)
- {
- vec.push_back(*itr);
- }
- return vec;
-}
-
-const StateSet::AttributeVector StateSet::getAttributeVector() const
-{
- AttributeVector vec;
- for (AttributeList::const_iterator itr = _attributeList.begin();
- itr!=_attributeList.end();
- ++itr)
- {
- vec.push_back(itr->second.first.get());
- }
- return vec;
-}
-
void StateSet::setRenderingHint(const int hint)
{
_renderingHint = hint;
diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp
index 137c9cdd1..d09abf3f4 100644
--- a/src/osg/Texture.cpp
+++ b/src/osg/Texture.cpp
@@ -46,6 +46,50 @@ Texture::~Texture()
dirtyTextureObject();
}
+int Texture::compare(const StateAttribute& sa) const
+{
+ // check the types are equal and then create the rhs variable
+ // used by the COMPARE_StateAttribute_Paramter macro's below.
+ COMPARE_StateAttribute_Types(Texture,sa)
+
+ if (_image!=rhs._image) // smart pointer comparison.
+ {
+ if (_image.valid())
+ {
+ if (rhs._image.valid())
+ {
+ if (_image->getFileName()getFileName()) return -1;
+ else if (_image->getFileName()>rhs._image->getFileName()) return 1;;
+ }
+ else
+ {
+ return 1; // valid lhs._image is greater than null.
+ }
+ }
+ else if (rhs._image.valid())
+ {
+ return -1; // valid rhs._image is greater than null.
+ }
+ }
+
+ // compare each paramter in turn against the rhs.
+ COMPARE_StateAttribute_Parameter(_textureUnit)
+ COMPARE_StateAttribute_Parameter(_wrap_s)
+ COMPARE_StateAttribute_Parameter(_wrap_t)
+ COMPARE_StateAttribute_Parameter(_wrap_r)
+ COMPARE_StateAttribute_Parameter(_min_filter)
+ COMPARE_StateAttribute_Parameter(_mag_filter)
+ COMPARE_StateAttribute_Parameter(_internalFormatMode)
+ COMPARE_StateAttribute_Parameter(_internalFormatValue)
+ COMPARE_StateAttribute_Parameter(_textureWidth)
+ COMPARE_StateAttribute_Parameter(_textureHeight)
+ COMPARE_StateAttribute_Parameter(_subloadMode)
+ COMPARE_StateAttribute_Parameter(_subloadOffsX)
+ COMPARE_StateAttribute_Parameter(_subloadOffsY)
+
+ return 0; // passed all the above comparison macro's, must be equal.
+}
+
void Texture::setImage(Image* image)
{
// delete old texture objects.
@@ -410,7 +454,7 @@ void Texture::applyImmediateMode(State& state) const
* OpenGL texture objects to cached until they can be deleted
* by the OpenGL context in which they were created, specified
* by contextID.*/
-void Texture::deleteTextureObject(uint contextID,uint handle)
+void Texture::deleteTextureObject(uint contextID,GLuint handle)
{
if (handle!=0)
{
@@ -443,7 +487,7 @@ void Texture::copyTexImage2D(State& state, int x, int y, int width, int height )
const uint contextID = state.getContextID();
// get the globj for the current contextID.
- uint& handle = getHandle(contextID);
+ GLuint& handle = getHandle(contextID);
if (handle)
{
@@ -484,7 +528,6 @@ void Texture::copyTexImage2D(State& state, int x, int y, int width, int height )
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _wrap_t );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _min_filter );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _mag_filter );
-// glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, width, height, 0 );
@@ -515,7 +558,6 @@ void Texture::copyTexSubImage2D(State& state, int xoffset, int yoffset, int x, i
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _wrap_t );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _min_filter );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _mag_filter );
-// glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, xoffset,yoffset, x, y, width, height);
/* Redundant, delete later */
diff --git a/src/osg/Timer.cpp b/src/osg/Timer.cpp
index 19c0c103c..dfce9b883 100644
--- a/src/osg/Timer.cpp
+++ b/src/osg/Timer.cpp
@@ -1,273 +1,203 @@
-#include
+//#include
#include
#include
-#ifndef macintosh
-#include
-#include
-#endif
-
#include
using namespace osg;
-#ifdef WIN32 // [
+// follows are the constructors of the Timer class, once version
+// for each OS combination. The order is WIN32, FreeBSD, Linux, IRIX,
+// and the rest of the world.
+//
+// all the rest of the timer methods are implemented within the header.
-#include
-#include
+#ifdef WIN32
-int Timer::inited = 0;
-double Timer::cpu_mhz = 0.0;
-
-void Timer::init( void )
-{
- Timer_t start_time = tick();
- Sleep (1000);
- Timer_t end_time = tick();
- cpu_mhz = (double)(end_time-start_time)*1e-6;
- inited = 1;
-}
-
-
-Timer::Timer( void )
-{
- if( !inited ) init();
-}
-
-
-Timer::~Timer( void )
-{
-}
-
-
-double Timer::delta_s( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return (((double)delta/cpu_mhz)*1e-6);
-}
-
-
-double Timer::delta_m( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return (((double)delta/cpu_mhz)*1e-3);
-}
-
-
-Timer_t Timer::delta_u( Timer_t t0, Timer_t t1 )
-{
- return (Timer_t)((double)(t1 - t0)/cpu_mhz);
-}
-
-
-Timer_t Timer::delta_n( Timer_t t0, Timer_t t1 )
-{
- return (Timer_t)((double)(t1 - t0) * 1e3/cpu_mhz);
-}
-#endif // ]
-
-#if defined(__linux) || defined(__FreeBSD__) // [
-
-# include
-# if defined(__linux)
-# include
-# elif defined(__FreeBSD__)
-# include
-# include
-# endif
-
-int Timer::inited = 0;
-double Timer::cpu_mhz = 0.0;
-
-void Timer::init( void )
-{
-# if defined(__FreeBSD__)
- int cpuspeed;
- size_t len;
-
- len = sizeof(cpuspeed);
- if (sysctlbyname("machdep.tsc_freq", &cpuspeed, &len, NULL, NULL) == -1) {
- perror("sysctlbyname(machdep.tsc_freq)");
- return;
- }
- cpu_mhz = cpuspeed / 1e6;
-
-# elif defined(__linux)
- char buff[128];
- FILE *fp = fopen( "/proc/cpuinfo", "r" );
-
- while( fgets( buff, sizeof( buff ), fp ) > 0 )
+ #include
+ #include
+ #include
+ #include
+ Timer::Timer()
{
- if( !strncmp( buff, "cpu MHz", strlen( "cpu MHz" )))
- {
- char *ptr = buff;
+ _useStandardClock = false;
+
+ if (_useStandardClock)
+ {
+ _secsPerClick = (1.0 / (double) CLOCKS_PER_SEC);
+ }
+ else
+ {
- while( ptr && *ptr != ':' ) ptr++;
- if( ptr )
- {
- ptr++;
- sscanf( ptr, "%lf", &cpu_mhz );
- }
- break;
- }
+ Timer_t start_time = tick();
+ Sleep (1000);
+ Timer_t end_time = tick();
+
+ _secsPerClick = 1.0/(double)(end_time-start_time);
+ }
}
- fclose( fp );
-# endif
- inited = 1;
-}
+#elif defined(__FreeBSD__)
-Timer::Timer( void )
-{
- if( !inited ) init();
-}
-
-
-Timer::~Timer( void )
-{
-}
-
-
-double Timer::delta_s( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return ((double)delta/cpu_mhz*1e-6);
-}
-
-
-double Timer::delta_m( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return ((double)delta/cpu_mhz*1e-3);
-}
-
-
-Timer_t Timer::delta_u( Timer_t t0, Timer_t t1 )
-{
- return (Timer_t)((double)(t1 - t0)/cpu_mhz);
-}
-
-
-Timer_t Timer::delta_n( Timer_t t0, Timer_t t1 )
-{
- return (Timer_t)((double)(t1 - t0) * 1e3/cpu_mhz);
-}
-#endif // ]
-#ifdef __sgi // [
-
-#include
-#include
-#include
-#include
-
-unsigned long Timer::dummy = 0;
-
-Timer::Timer( void )
-{
- __psunsigned_t phys_addr, raddr;
- unsigned int cycleval;
- volatile unsigned long counter_value, *iotimer_addr;
- int fd, poffmask;
-
- poffmask = getpagesize() - 1;
- phys_addr = syssgi( SGI_QUERY_CYCLECNTR, &cycleval );
- microseconds_per_click = (double)cycleval/1e6;
- nanoseconds_per_click = (double)cycleval/1e3;
- raddr = phys_addr & ~poffmask;
-
- clk = &dummy;
-
- if( (fd = open( "/dev/mmem", O_RDONLY )) < 0 )
+ #include
+ #include
+ #include
+ #include
+ #include
+ Timer::Timer()
{
- perror( "/dev/mmem" );
- return;
+ _useStandardClock = false;
+
+ if (_useStandardClock)
+ {
+ _secsPerClick = 1e-6; // gettimeofday()'s precision.
+ }
+ else
+ {
+ int cpuspeed;
+ size_t len;
+
+ len = sizeof(cpuspeed);
+ if (sysctlbyname("machdep.tsc_freq", &cpuspeed, &len, NULL, NULL) == -1)
+ {
+ _useStandardClock = true;
+ perror("sysctlbyname(machdep.tsc_freq)");
+ return;
+ }
+
+ _secsPerClick = 1.0/cpuspeed;
+ }
+ }
+
+#elif defined(__linux)
+
+ #include
+ #include
+ #include
+ #include
+
+ Timer::Timer()
+ {
+ _useStandardClock = false;
+
+ if (_useStandardClock)
+ {
+ _secsPerClick = 1e-6; // gettimeofday()'s precision.
+ }
+ else
+ {
+ char buff[128];
+ FILE *fp = fopen( "/proc/cpuinfo", "r" );
+
+ double cpu_mhz=0.0f;
+
+ while( fgets( buff, sizeof( buff ), fp ) > 0 )
+ {
+ if( !strncmp( buff, "cpu MHz", strlen( "cpu MHz" )))
+ {
+ char *ptr = buff;
+
+ while( ptr && *ptr != ':' ) ptr++;
+ if( ptr )
+ {
+ ptr++;
+ sscanf( ptr, "%lf", &cpu_mhz );
+ }
+ break;
+ }
+ }
+ fclose( fp );
+
+ if (cpu_mhz==0.0f)
+ {
+ // error - no cpu_mhz found.
+ Timer_t start_time = tick();
+ sleep (1);
+ Timer_t end_time = tick();
+ _secsPerClick = 1.0/(double)(end_time-start_time);
+ }
+ else
+ {
+ _secsPerClick = 1e-6/cpu_mhz;
+ }
+ }
}
- iotimer_addr = (volatile unsigned long *)mmap(
- (void *)0L,
- (size_t)poffmask,
- (int)PROT_READ,
- (int)MAP_PRIVATE, fd, (off_t)raddr);
+#elif defined(__sgi)
- iotimer_addr = (unsigned long *)(
- (__psunsigned_t)iotimer_addr + (phys_addr & poffmask)
- );
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
- cycleCntrSize = syssgi( SGI_CYCLECNTR_SIZE );
+ unsigned long Timer::_dummy = 0;
- if( cycleCntrSize > 32 )
- ++iotimer_addr;
+ Timer::Timer( void )
+ {
+ _useStandardClock = false;
- clk = (unsigned long *)iotimer_addr;
-}
+ if (_useStandardClock)
+ {
+ _secsPerClick = 1e-6; // gettimeofday()'s precision.
+ }
+ else
+ {
+ __psunsigned_t phys_addr, raddr;
+ unsigned int cycleval;
+ volatile unsigned long counter_value, *iotimer_addr;
+ int fd, poffmask;
+
+ poffmask = getpagesize() - 1;
+ phys_addr = syssgi( SGI_QUERY_CYCLECNTR, &cycleval );
+ raddr = phys_addr & ~poffmask;
+
+ _clockAddress = &_dummy;
+
+ if( (fd = open( "/dev/mmem", O_RDONLY )) < 0 )
+ {
+ perror( "/dev/mmem" );
+ return;
+ }
+
+ iotimer_addr = (volatile unsigned long *)mmap(
+ (void *)0L,
+ (size_t)poffmask,
+ (int)PROT_READ,
+ (int)MAP_PRIVATE, fd, (off_t)raddr);
+
+ iotimer_addr = (unsigned long *)(
+ (__psunsigned_t)iotimer_addr + (phys_addr & poffmask)
+ );
+
+ _cycleCntrSize = syssgi( SGI_CYCLECNTR_SIZE );
+
+ if( _cycleCntrSize > 32 )
+ ++iotimer_addr;
+
+ _clockAddress = (unsigned long *)iotimer_addr;
+ _secsPerClick = (double)(cycleval)* 1e-12;
+ }
+ }
-Timer::~Timer( void )
-{
-}
+#elif defined(unix)
+ Timer::Timer( void )
+ {
+ _useStandardClock = true;
+ _secsPerClick = 1e-6; // gettimeofday()'s precision.
+ }
-double Timer::delta_s( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return ((double)delta * microseconds_per_click*1e-6);
-}
+#else
+ // handle the rest of the OS world by just using the std::clock,
-double Timer::delta_m( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return ((double)delta * microseconds_per_click*1e-3);
-}
+ Timer::Timer( void )
+ {
+ _useStandardClock = true;
+ _secsPerClick = (1.0 / (double) CLOCKS_PER_SEC);
+ }
-
-Timer_t Timer::delta_u( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return (Timer_t)((double)delta * microseconds_per_click);
-}
-
-Timer_t Timer::delta_n( Timer_t t1, Timer_t t2 )
-{
- unsigned long delta = t2 - t1;
- return (Timer_t )((double)delta * nanoseconds_per_click);
-}
-
-#endif // ]
-
-#ifdef macintosh // [
-
-Timer::Timer( void )
-{
- microseconds_per_click = (1.0 / (double) CLOCKS_PER_SEC) * 1e6;
- nanoseconds_per_click = (1.0 / (double) CLOCKS_PER_SEC) * 1e9;
-}
-
-Timer::~Timer( void )
-{
-}
-
-double Timer::delta_s( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return ((double)delta * microseconds_per_click*1e-6);
-}
-
-double Timer::delta_m( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return ((double)delta * microseconds_per_click*1e-3);
-}
-
-Timer_t Timer::delta_u( Timer_t t1, Timer_t t2 )
-{
- Timer_t delta = t2 - t1;
- return (Timer_t)((double)delta * microseconds_per_click);
-}
-
-Timer_t Timer::delta_n( Timer_t t1, Timer_t t2 )
-{
- unsigned long delta = t2 - t1;
- return (Timer_t )((double)delta * nanoseconds_per_click);
-}
-#endif // ]
+#endif
diff --git a/src/osgGLUT/Viewer.cpp b/src/osgGLUT/Viewer.cpp
index 1835dfa09..234dfc0c4 100644
--- a/src/osgGLUT/Viewer.cpp
+++ b/src/osgGLUT/Viewer.cpp
@@ -75,8 +75,8 @@ Viewer::Viewer()
fullscreen = false;
_is_open = 0;
_saved_wx = wx = _saved_wy = wy = 0;
- _saved_ww = ww = 1024,
- _saved_wh = wh = 768;
+ _saved_ww = ww = 800,
+ _saved_wh = wh = 600;
_title = "OSG Viewer";
@@ -119,6 +119,10 @@ Viewer::Viewer()
frRate=0; // added by gwm to display fram Rate smoothed
_focusedViewport = 0; // The viewport with mouse/keyboard focus
+
+
+ _frameStamp = new osg::FrameStamp;
+
}
@@ -203,7 +207,9 @@ bool Viewer::open()
Node* node = itr->sceneView->getSceneData();
if (node) node->accept(vrv);
}
-
+#ifdef _DEBUG
+ vrv.setMinimumNumStencilBits(8); //gwm 12.8.01 to force stencils available for DC test
+#endif
// set up each render stage to clear the appropriate buffers.
GLbitfield clear_mask=0;
if (vrv.requiresRGB()) clear_mask |= GL_COLOR_BUFFER_BIT;
@@ -322,11 +328,13 @@ float Viewer::app(unsigned int viewport)
osg::Timer_t beforeApp = _timer.tick();
// do app traversal.
+
+ getViewportSceneView(viewport)->setFrameStamp(_frameStamp.get());
getViewportSceneView(viewport)->app();
// update the camera manipulator.
osg::ref_ptr ea = new GLUTEventAdapter;
- ea->adaptFrame(clockSeconds());
+ ea->adaptFrame(_frameStamp->getReferenceTime());
if (_viewportList[viewport]._cameraManipulator->handle(*ea,*this))
{
@@ -757,7 +765,8 @@ void Viewer::showStats()
int wid=ww, ht=wh; // temporary local screen size - must change during this section
if (wid>0 && ht>0) {
const int blsize=16;
- char *clin=new char[wid/blsize+2]; // buffer to print
+ char *clin=new char[wid/blsize+2]; // buffer to print dc
+ char *ctext=new char[128]; // buffer to print details
float mdc=0;
GLubyte *buffer=new GLubyte[wid*ht];
if (buffer) {
@@ -786,13 +795,14 @@ void Viewer::showStats()
*clpt='\0';
displaytext(0,(int)(0.84f*vh-(j*12)/blsize),clin); // display average DC over the blsize box
}
- sprintf(clin, "Pixels hit %.1f Mean DC %.2f: %4d by %4d pixels.", mdc, mdc/(wid*ht), wid, ht);
+ sprintf(ctext, "Pixels hit %.1f Mean DC %.2f: %4d by %4d pixels.", mdc, mdc/(wid*ht), wid, ht);
displaytext(0,(int)(0.86f*vh),clin);
glEnable(GL_STENCIL_TEST); // re-enable stencil buffer counting
delete [] buffer;
}
delete [] clin;
+ delete [] ctext;
}
}
@@ -803,9 +813,12 @@ void Viewer::showStats()
glPopMatrix();
}
-
void Viewer::display()
{
+
+ _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1);
+ _frameStamp->setReferenceTime(clockSeconds());
+
// application traverasal.
times[2].timeApp=0.0f;
@@ -828,7 +841,7 @@ void Viewer::display()
}
- glFinish();
+ if (_printStats>1) glFinish();
times[2].frameend=updateFrameTick(); // absolute time
@@ -841,9 +854,12 @@ void Viewer::display()
times[1]=times[2];
}
+
glutSwapBuffers(); // moved after draw of stats & glFinish() to get accurate timing (excluding stat draw!)
// cout << "Time elapsed "<<_timer.delta_s(_initialTick,_timer.tick())<1) glFinish();
+
#ifdef SGV_USE_RTFS
fs->frame();
#endif
@@ -1028,14 +1044,19 @@ void Viewer::keyboard(unsigned char key, int x, int y)
break;
case 'p' :
+ if (_printStats==4) glDisable(GL_STENCIL_TEST); // switch off stencil counting
_printStats++; //gwm jul 2001 range of possible outputs, 0-4 = !_printStats;
if (_printStats>4) _printStats=0;
if (_printStats==4) { // count depth complexity by incrementing the stencil buffer every
// time a pixel is hit
- glEnable(GL_STENCIL_TEST);
- glStencilOp(GL_INCR ,GL_INCR ,GL_INCR);
- } else {
- glDisable(GL_STENCIL_TEST);
+ int nsten=0; // Number of stencil planes available
+ glGetIntegerv(GL_STENCIL_BITS , &nsten);
+ if (nsten>0) {
+ glEnable(GL_STENCIL_TEST);
+ glStencilOp(GL_INCR ,GL_INCR ,GL_INCR);
+ } else {// skip this option
+ _printStats++;
+ }
}
break;
@@ -1409,11 +1430,11 @@ void Viewer::addViewport(osgUtil::SceneView* sv,
void Viewer::addViewport(osg::Node* rootnode,
float x, float y, float width, float height)
{
- osgUtil::SceneView *sceneView = new osgUtil::SceneView;
- sceneView->setDefaults();
- sceneView->setSceneData(rootnode);
+ osgUtil::SceneView *sceneView = new osgUtil::SceneView;
+ sceneView->setDefaults();
+ sceneView->setSceneData(rootnode);
- addViewport( sceneView, x, y, width, height );
+ addViewport( sceneView, x, y, width, height );
}
void Viewer::init(osg::Node* rootnode)
diff --git a/src/osgPlugins/osg/GeoSet.cpp b/src/osgPlugins/osg/GeoSet.cpp
index ad481a017..dabfd4290 100644
--- a/src/osgPlugins/osg/GeoSet.cpp
+++ b/src/osgPlugins/osg/GeoSet.cpp
@@ -874,6 +874,7 @@ bool GeoSet_writeLocalData(const Object& obj, Output& fw)
fw << (int)*itrRowData<<" ";
itrRowData += 1;
}
+ itrRowComp++;
}
fw << endl;
diff --git a/src/osgPlugins/osg/StateSet.cpp b/src/osgPlugins/osg/StateSet.cpp
index 86660d41a..7fbe1b73f 100644
--- a/src/osgPlugins/osg/StateSet.cpp
+++ b/src/osgPlugins/osg/StateSet.cpp
@@ -377,42 +377,6 @@ bool StateSet_writeLocalData(const Object& obj, Output& fw)
}
-#ifdef WIN32
- #define USE_VECTOR_VERSIONS
-#endif
-
-#ifdef USE_VECTOR_VERSIONS
-
- StateSet::ModeVector modes = stateset.getModeVector();
-
- for(StateSet::ModeVector::iterator mitr=modes.begin();
- mitr!=modes.end();
- ++mitr)
- {
- GLModeToGLNameMap::iterator nitr = s_GLModeToGLNameMap.find(mitr->first);
- if (nitr!=s_GLModeToGLNameMap.end())
- {
- fw.indent() << nitr->second << " " << StateSet_getModeStr(mitr->second) << endl;
- }
- else
- {
- // no name defined for GLMode so just pass its value to fw.
- fw.indent() << "0x" << hex << (osg::uint)mitr->first << dec <<" " << StateSet_getModeStr(mitr->second) << endl;
- }
-
- }
-
- StateSet::AttributeVector attributes = stateset.getAttributeVector();
-
- for(StateSet::AttributeVector::iterator sitr=attributes.begin();
- sitr!=attributes.end();
- ++sitr)
- {
- fw.writeObject(*(*sitr));
- }
-
-#else
-
const StateSet::ModeList& ml = stateset.getModeList();
const StateSet::AttributeList& sl = stateset.getAttributeList();
@@ -439,8 +403,6 @@ bool StateSet_writeLocalData(const Object& obj, Output& fw)
fw.writeObject(*(sitr->second.first));
}
-#endif
-
return true;
}
diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp
index bdb07d98d..77b23b94a 100644
--- a/src/osgUtil/CullVisitor.cpp
+++ b/src/osgUtil/CullVisitor.cpp
@@ -80,8 +80,6 @@ class PrintVisitor : public NodeVisitor
CullVisitor::CullVisitor()
{
- _frameNumber = 0;
-
// overide the default node visitor mode.
setTraversalMode(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
@@ -109,10 +107,7 @@ CullVisitor::CullVisitor()
_calculated_znear = FLT_MAX;
_calculated_zfar = -FLT_MAX;
- _view[0] = 0;
- _view[1] = 0;
- _view[2] = 1024;
- _view[3] = 768;
+ _viewport = NULL;
_impostorActive = true;
_depthSortImpostorSprites = false;
@@ -682,8 +677,14 @@ void CullVisitor::apply(Impostor& node)
// traverse the appropriate child of the LOD.
node.getChild(eval)->accept(*this);
}
- else
+ else if (!_viewport.valid())
{
+ // need to use impostor but no valid viewport is defined to simply
+ // default to using the LOD child as above.
+ node.getChild(eval)->accept(*this);
+ }
+ else
+ {
// within the impostor distance threshold therefore attempt
// to use impostor instead.
@@ -695,7 +696,7 @@ void CullVisitor::apply(Impostor& node)
if (impostorSprite)
{
// impostor found, now check to see if it is good enough to use
- float error = impostorSprite->calcPixelError(*_camera,_view,matrix);
+ float error = impostorSprite->calcPixelError(*_camera,*_viewport,matrix);
if (error>_impostorPixelErrorThreshold)
{
@@ -765,7 +766,7 @@ void CullVisitor::apply(Impostor& node)
if (stateset) popStateSet();
// update frame number to show that impostor is in action.
- impostorSprite->setLastFrameUsed(_frameNumber);
+ impostorSprite->setLastFrameUsed(getTraversalNumber());
}
else
@@ -1085,8 +1086,8 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node)
// equivilant window coordinates by using the camera's project method.
Vec3 c00_win;
Vec3 c11_win;
- _camera->project(c00_world,_view,c00_win);
- _camera->project(c11_world,_view,c11_win);
+ _camera->project(c00_world,*_viewport,c00_win);
+ _camera->project(c11_world,*_viewport,c11_win);
// adjust texture size to be nearest power of 2.
@@ -1114,17 +1115,26 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node)
int new_t = (int)(powf(2.0f,rounded_tp2));
// if dimension is bigger than window divide it down.
- while (new_s>_view[2]) new_s /= 2;
+ while (new_s>_viewport->width()) new_s /= 2;
// if dimension is bigger than window divide it down.
- while (new_t>_view[3]) new_t /= 2;
+ while (new_t>_viewport->height()) new_t /= 2;
- rtts->setViewport(_view[0],_view[1],new_s,new_t);
+
+ // offset the impostor viewport from the center of the main window
+ // viewport as often the edges of the viewport might be obscured by
+ // other windows, which can cause image/reading writing problems.
+ int center_x = _viewport->x()+_viewport->width()/2;
+ int center_y = _viewport->y()+_viewport->height()/2;
+
+ Viewport* viewport = new Viewport;
+ viewport->setViewport(center_x-new_s/2,center_y-new_t/2,new_s,new_t);
+ rtts->setViewport(viewport);
// create the impostor sprite.
ImpostorSprite* impostorSprite =
- _impostorSpriteManager->createOrReuseImpostorSprite(new_s,new_t,_frameNumber-_numFramesToKeepImpostorSprites);
+ _impostorSpriteManager->createOrReuseImpostorSprite(new_s,new_t,getTraversalNumber()-_numFramesToKeepImpostorSprites);
if (impostorSprite==NULL) return NULL;
@@ -1143,7 +1153,7 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node)
Texture* texture = impostorSprite->getTexture();
// update frame number to show that impostor is in action.
- impostorSprite->setLastFrameUsed(_frameNumber);
+ impostorSprite->setLastFrameUsed(getTraversalNumber());
Vec3* coords = impostorSprite->getCoords();
Vec2* texcoords = impostorSprite->getTexCoords();
diff --git a/src/osgUtil/Makefile b/src/osgUtil/Makefile
index 7093a4b4f..1cd85c5d6 100644
--- a/src/osgUtil/Makefile
+++ b/src/osgUtil/Makefile
@@ -2,6 +2,7 @@
include ../../Make/makedefs
C++FILES = \
+ AppVisitor.cpp\
CameraManipulator.cpp\
CullVisitor.cpp\
CullViewState.cpp\
@@ -12,6 +13,7 @@ C++FILES = \
IntersectVisitor.cpp\
InsertImpostorsVisitor.cpp\
NvTriStripObjects.cpp\
+ OptimizeStateVisitor.cpp\
RenderBin.cpp\
RenderGraph.cpp\
RenderLeaf.cpp\
@@ -39,6 +41,7 @@ LIB = ../../lib/lib$(TARGET_BASENAME).so
TARGET_LIB_FILES = lib$(TARGET_BASENAME).so
TARGET_INCLUDE_FILES = \
+ osgUtil/AppVisitor\
osgUtil/CameraManipulator\
osgUtil/CullVisitor\
osgUtil/CullViewState\
@@ -52,6 +55,7 @@ TARGET_INCLUDE_FILES = \
osgUtil/GUIEventHandler\
osgUtil/IntersectVisitor\
osgUtil/InsertImpostorsVisitor\
+ osgUtil/OptimizeStateVisitor\
osgUtil/RenderBin\
osgUtil/RenderGraph\
osgUtil/RenderLeaf\
diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp
index 8e48aee06..165880482 100644
--- a/src/osgUtil/RenderStage.cpp
+++ b/src/osgUtil/RenderStage.cpp
@@ -1,3 +1,5 @@
+#include
+
#include
using namespace osg;
@@ -44,6 +46,12 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
{
if (_stageDrawnThisFrame) return;
+ if (!_viewport)
+ {
+ notify(FATAL) << "Error: cannot drawm stage due to undefined viewport."<x(), _viewport->y(), _viewport->width(), _viewport->height() );
glEnable( GL_SCISSOR_TEST );
#endif
- glViewport( _view[0], _view[1], _view[2], _view[3] );
+ _viewport->apply(state);
// glEnable( GL_DEPTH_TEST );
@@ -86,6 +94,10 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
glDisable( GL_SCISSOR_TEST );
#endif
+ // pass the camera we're about to set up to state, so that
+ // subsequent operatiosn know about it, such as for CLOD etc.
+ state.setCamera(_camera.get());
+
// set up projection
const Matrix& projectionMat = _camera->getProjectionMatrix();
glMatrixMode( GL_PROJECTION );
@@ -104,6 +116,7 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
// set up camera modelview.
const Matrix& modelView = _camera->getModelViewMatrix();
glMultMatrixf((GLfloat*)modelView._mat);
+
if (getLightingMode()==RenderStageLighting::SKY_LIGHT && light)
{
diff --git a/src/osgUtil/RenderToTextureStage.cpp b/src/osgUtil/RenderToTextureStage.cpp
index 471ee9594..7078348ab 100644
--- a/src/osgUtil/RenderToTextureStage.cpp
+++ b/src/osgUtil/RenderToTextureStage.cpp
@@ -27,6 +27,7 @@ void RenderToTextureStage::draw(osg::State& state,RenderLeaf*& previous)
RenderStage::draw(state,previous);
// now copy the rendered image to attached texture.
- if (_texture.valid()) _texture->copyTexImage2D(state,_view[0],_view[1],_view[2],_view[3]);
+ if (_texture.valid())
+ _texture->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height());
}
diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp
index b0ea80398..8a9c81b0e 100644
--- a/src/osgUtil/SceneView.cpp
+++ b/src/osgUtil/SceneView.cpp
@@ -1,4 +1,5 @@
#include
+#include
#include
#include
@@ -25,12 +26,7 @@ SceneView::SceneView()
_prioritizeTextures = false;
- _view[0] = 0;
- _view[1] = 0;
- _view[2] = 1024;
- _view[3] = 768;
-
- _frameNumber = 0;
+ _viewport = new Viewport;
}
@@ -58,6 +54,10 @@ void SceneView::setDefaults()
_rendergraph = new osgUtil::RenderGraph;
_renderStage = new osgUtil::RenderStage;
+
+ _appVisitor = new osgUtil::AppVisitor;
+
+
_cullVisitor = new osgUtil::CullVisitor;
_cullVisitor->setRenderGraph(_rendergraph.get());
@@ -88,26 +88,43 @@ void SceneView::setDefaults()
void SceneView::app()
{
- ++_frameNumber;
-
if (_sceneData.valid() && _appVisitor.valid())
{
_appVisitor->reset();
+
+ _appVisitor->setFrameStamp(_frameStamp.get());
+
+ // use the frame number for the traversal number.
+ if (_frameStamp.valid())
+ {
+ _appVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
+ }
+
_sceneData->accept(*_appVisitor.get());
}
+
+
}
void SceneView::cull()
{
if (!_sceneData) return;
- _camera->adjustAspectRatio((GLfloat)_view[2]/(GLfloat) _view[3]);
+ _camera->adjustAspectRatio(_viewport->aspectRatio());
_rendergraph->clean();
_cullVisitor->reset();
+ _cullVisitor->setFrameStamp(_frameStamp.get());
+
+ // use the frame number for the traversal number.
+ if (_frameStamp.valid())
+ {
+ _cullVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
+ }
+
// comment out reset of rendergraph since clean is more efficient.
// _rendergraph->reset();
@@ -115,14 +132,13 @@ void SceneView::cull()
// reuse the structure on the rendergraph in the next frame. This
// achieves a certain amount of frame cohereancy of memory allocation.
- _cullVisitor->setFrameNumber(_frameNumber);
_cullVisitor->setLODBias(_lodBias);
_cullVisitor->setCamera(*_camera);
- _cullVisitor->setViewport(_view[0],_view[1],_view[2],_view[3]);
+ _cullVisitor->setViewport(_viewport.get());
_renderStage->reset();
- _renderStage->setViewport(_view[0],_view[1],_view[2],_view[3]);
+ _renderStage->setViewport(_viewport.get());
_renderStage->setCamera(_camera.get());
_renderStage->setClearColor(_backgroundColor);
_renderStage->setLight(_light.get());
@@ -207,6 +223,8 @@ void SceneView::draw()
}
// we in theory should be able to
_state->reset();
+
+ _state->setFrameStamp(_frameStamp.get());
// note, to support multi-pipe systems the deletion of OpenGL display list
// and texture objects is deferred until the OpenGL context is the correct
@@ -233,7 +251,7 @@ void SceneView::draw()
windows coordinates are calculated relative to the bottom left of the window.*/
bool SceneView::projectWindowIntoObject(const osg::Vec3& window,osg::Vec3& object) const
{
- return _camera->unproject(window,_view,object);
+ return _camera->unproject(window,*_viewport,object);
}
@@ -244,8 +262,8 @@ bool SceneView::projectWindowIntoObject(const osg::Vec3& window,osg::Vec3& objec
windows coordinates are calculated relative to the bottom left of the window.*/
bool SceneView::projectWindowXYIntoObject(int x,int y,osg::Vec3& near_point,osg::Vec3& far_point) const
{
- bool result_near = _camera->unproject(Vec3(x,y,0.0f),_view,near_point);
- bool result_far = _camera->unproject(Vec3(x,y,1.0f),_view,far_point);
+ bool result_near = _camera->unproject(Vec3(x,y,0.0f),*_viewport,near_point);
+ bool result_far = _camera->unproject(Vec3(x,y,1.0f),*_viewport,far_point);
return result_near & result_far;
}
@@ -256,5 +274,5 @@ bool SceneView::projectWindowXYIntoObject(int x,int y,osg::Vec3& near_point,osg:
windows coordinates are calculated relative to the bottom left of the window.*/
bool SceneView::projectObjectIntoWindow(const osg::Vec3& object,osg::Vec3& window) const
{
- return _camera->project(object,_view,window);
+ return _camera->project(object,*_viewport,window);
}