Synch with 20010921

This commit is contained in:
Don BURNS
2001-09-22 02:42:08 +00:00
parent d47b8f9c1f
commit 7ae58df42a
197 changed files with 7867 additions and 6189 deletions

View File

@@ -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

View File

@@ -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();

View File

@@ -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 <osg/Geode>
@@ -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();

View File

@@ -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);

View File

@@ -15,7 +15,8 @@
#include <GL/glut.h>
#include <osgGLUT/Viewer>
#include <osg/Quat>
#include <osgUtil/OptimizeStateVisitor>
/*
* 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 = "<<timer.delta_s(before_load,after_load)<<" seconds"<<endl;
// note, the Microsoft visual C++ compilers can't handle the STL
// in the OptimizeStateVisitor and crash if we run it. For the
// time being we'll just not use the optimize visitor under windows.
#ifndef WIN32
// optimize the state in scene graph, removing duplicate state.
osgUtil::OptimizeStateVisitor osv;
rootnode->accept(osv);
osv.optimize();
#endif
// initialize the viewer.
osgGLUT::Viewer viewer;
viewer.addViewport( rootnode );

View File

@@ -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;

View File

@@ -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="<<fovx<<",fovy="<<fovy<<","<<endl;
notify(INFO)<<" zNear="<<zNear<<", zFar="<<zFar<<")"<<endl;
notify(INFO)<<" osg::Camera::calc_fovx()="<<calc_fovx()<<endl;
notify(INFO)<<" osg::Camera::calc_fovy()="<<calc_fovy()<<endl;
_dirty = true;
}
/** Set the near and far clipping planes.*/
void Camera::setNearFar(const double zNear, const double zFar)
@@ -134,7 +164,7 @@ void Camera::setNearFar(const double zNear, const double zFar)
/** Adjust the clipping planes to account for a new window aspcect ratio.
* Typicall used after resizeing a window.*/
void Camera::adjustAspectRatio(const double newAspectRatio, const AdjustAxis aa)
void Camera::adjustAspectRatio(const double newAspectRatio, const AdjustAspectRatioMode aa)
{
double previousAspectRatio = (_right-_left)/(_top-_bottom);
double deltaRatio = newAspectRatio/previousAspectRatio;
@@ -668,15 +698,15 @@ void Camera::ensureOrthogonalUpVector()
_up.normalize();
}
const bool Camera::project(const Vec3& obj,const int* view,Vec3& win) const
const bool Camera::project(const Vec3& obj,const Viewport& viewport,Vec3& win) const
{
if (_MP.valid())
{
Vec3 v = obj * (*_MP);
win.set(
view[0] + view[2]*(v[0]+1.0f)*0.5f,
view[1] + view[3]*(v[1]+1.0f)*0.5f,
(float)viewport.x() + (float)viewport.width()*(v[0]+1.0f)*0.5f,
(float)viewport.y() + (float)viewport.height()*(v[1]+1.0f)*0.5f,
(v[2]+1.0f)*0.5f
);
@@ -686,13 +716,13 @@ const bool Camera::project(const Vec3& obj,const int* view,Vec3& win) const
return false;
}
const bool Camera::unproject(const Vec3& win,const int* view,Vec3& obj) const
const bool Camera::unproject(const Vec3& win,const Viewport& viewport,Vec3& obj) const
{
if (_inverseMP.valid())
{
Vec3 v(
2.0f*(win[0]-view[0])/view[2] - 1.0f,
2.0f*(win[1]-view[1])/view[3] - 1.0f,
2.0f*(win[0]-(float)viewport.x())/viewport.width() - 1.0f,
2.0f*(win[1]-(float)viewport.y())/viewport.height() - 1.0f,
2.0f*(win[2]) - 1.0f
);

View File

@@ -5,7 +5,6 @@ using namespace osg;
ClipPlane::ClipPlane()
{
_clipPlane = new double[4];
_clipPlane[0] = 0.0;
_clipPlane[1] = 0.0;
_clipPlane[2] = 0.0;
@@ -16,7 +15,6 @@ ClipPlane::ClipPlane()
ClipPlane::~ClipPlane()
{
delete _clipPlane;
}
void ClipPlane::setClipPlane(const Vec4& plane)
@@ -68,17 +66,10 @@ void ClipPlane::getClipPlane(Plane& plane) const
void ClipPlane::getClipPlane(double* plane) const
{
if (plane)
{
plane[0] = _clipPlane[0];
plane[1] = _clipPlane[1];
plane[2] = _clipPlane[2];
plane[3] = _clipPlane[3];
}
else
{
notify(WARN)<<"Warning: ClipPlane::getClipPlane() passed NULL plane array, ignoring operation."<<endl;
}
plane[0] = _clipPlane[0];
plane[1] = _clipPlane[1];
plane[2] = _clipPlane[2];
plane[3] = _clipPlane[3];
}
void ClipPlane::setClipPlaneNum(const unsigned int num)

View File

@@ -2,13 +2,6 @@
#include <math.h>
#include "osg/Geode"
#include <algorithm>
#ifdef __sgi
using std::find;
using std::for_each;
#endif
#define square(x) ((x)*(x))
using namespace osg;

View File

@@ -5,12 +5,6 @@
#include <algorithm>
// #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;

View File

@@ -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 );

View File

@@ -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\

View File

@@ -1,418 +1,90 @@
#include <math.h>
#include <string.h>
#include <osg/Types>
#include <osg/Matrix>
#include <osg/Quat>
#include <osg/Notify>
#include <osg/ref_ptr>
#include <osg/Types>
#define square(x) ((x)*(x))
#define DEG2RAD(x) ((x)*M_PI/180.0)
#define RAD2DEG(x) ((x)*180.0/M_PI)
#include <cstdlib> //memcpy
#include <cmath> //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<const float*>(invm._mat);
const float* a = reinterpret_cast<const float*>(_m._mat);
float* b = reinterpret_cast<float*>(_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) );
}

View File

@@ -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) );
}

View File

@@ -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();

View File

@@ -5,8 +5,12 @@ using namespace osg;
NodeVisitor::NodeVisitor(TraversalMode tm)
{
_traversalNumber = -1;
_traversalVisitor = NULL;
_traversalMode = tm;
_traversalMask = 0xffffffff;
_nodeMaskOverride = 0x0;
}

View File

@@ -1,10 +1,6 @@
// Ideas and code borrowed from GLUT pointburst demo
// written by Mark J. Kilgard
#ifdef WIN32
#include <windows.h>
#endif
#include "osg/GL"
#include "osg/GLExtensions"
#include "osg/Point"

View File

@@ -8,7 +8,6 @@ using namespace osg;
State::State()
{
_contextID = 0;
_frameNumber = 0;
_fineGrainedErrorDetection = true;
}

View File

@@ -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;

View File

@@ -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()<rhs._image->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 */

View File

@@ -1,273 +1,203 @@
#include <stdlib.h>
//#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef macintosh
#include <sys/types.h>
#include <fcntl.h>
#endif
#include <osg/Timer>
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 <windows.h>
#include <winbase.h>
#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 <unistd.h>
# if defined(__linux)
# include <sys/mman.h>
# elif defined(__FreeBSD__)
# include <sys/types.h>
# include <sys/sysctl.h>
# 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 <sys/types.h>
#include <fcntl.h>
#include <windows.h>
#include <winbase.h>
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 <unistd.h>
#include <sys/syssgi.h>
#include <sys/immu.h>
#include <sys/mman.h>
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 <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/types.h>
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 <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
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 <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syssgi.h>
#include <sys/immu.h>
#include <sys/mman.h>
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

View File

@@ -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<GLUTEventAdapter> 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())<<endl;
if (_printStats>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)

View File

@@ -874,6 +874,7 @@ bool GeoSet_writeLocalData(const Object& obj, Output& fw)
fw << (int)*itrRowData<<" ";
itrRowData += 1;
}
itrRowComp++;
}
fw << endl;

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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\

View File

@@ -1,3 +1,5 @@
#include <osg/Notify>
#include <osgUtil/RenderStage>
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."<<endl;
return;
}
_stageDrawnThisFrame = true;
for(DependencyList::iterator itr=_dependencyList.begin();
@@ -57,11 +65,11 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
#define USE_SISSOR_TEST
#ifdef USE_SISSOR_TEST
glScissor( _view[0], _view[1], _view[2], _view[3] );
glScissor( _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)
{

View File

@@ -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());
}

View File

@@ -1,4 +1,5 @@
#include <osgUtil/SceneView>
#include <osgUtil/AppVisitor>
#include <osg/Notify>
#include <osg/Texture>
@@ -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);
}