void RigGeometry::accept(osg::NodeVisitor &nv) { if (!nv.validNodeMask(*this)) return; nv.pushOntoNodePath(this); if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR) cull(&nv); else if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) updateBounds(&nv); else nv.apply(*this); nv.popFromNodePath(); }
void PointDrawable::accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { osgUtil::CullVisitor* cv = Culling::asCullVisitor(nv); nv.pushOntoNodePath(this); // inject our shared stateset into the cull visitor. if (cv) cv->pushStateSet(_sharedStateSet.get()); nv.apply(*this); if (cv) cv->popStateSet(); nv.popFromNodePath(); } }
void PixelAutoTransform::accept( osg::NodeVisitor& nv ) { // optimization - don't bother with mathing if the node is hidden. // (this occurs in Node::accept, which we override here) if ( !nv.validNodeMask(*this) ) return; bool resetLodScale = false; double oldLodScale = 1.0; if ( nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR ) { // re-activate culling now that the first cull traversal has taken place. this->setCullingActive( true ); osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv); if ( cv ) { osg::Viewport::value_type width = _previousWidth; osg::Viewport::value_type height = _previousHeight; osg::Viewport* viewport = cv->getViewport(); if (viewport) { width = viewport->width(); height = viewport->height(); } osg::Vec3d eyePoint = cv->getEyeLocal(); osg::Vec3d localUp = cv->getUpLocal(); osg::Vec3d position = getPosition(); const osg::Matrix& projection = *(cv->getProjectionMatrix()); bool doUpdate = _firstTimeToInitEyePoint || _dirty; if ( !_firstTimeToInitEyePoint ) { osg::Vec3d dv = _previousEyePoint - eyePoint; if (dv.length2() > getAutoUpdateEyeMovementTolerance() * (eyePoint-getPosition()).length2()) { doUpdate = true; } else { osg::Vec3d dupv = _previousLocalUp - localUp; // rotating the camera only affects ROTATE_TO_* if ((_autoRotateMode && dupv.length2() > getAutoUpdateEyeMovementTolerance()) || (width != _previousWidth || height != _previousHeight) || (projection != _previousProjection) || (position != _previousPosition) ) { doUpdate = true; } } } _firstTimeToInitEyePoint = false; if ( doUpdate ) { if ( getAutoScaleToScreen() ) { double radius = _sizingNode.valid() ? _sizingNode->getBound().radius() : getNumChildren() > 0 ? getChild(0)->getBound().radius() : 0.48; double pixels = cv->pixelSize( getPosition(), radius ); double scaledMinPixels = _minPixels * _minimumScale; double scale = pixels < scaledMinPixels ? scaledMinPixels / pixels : 1.0; //OE_DEBUG << LC << "Pixels = " << pixels << ", minPix = " << _minPixels << ", scale = " << scale << std::endl; setScale( scale ); } _previousEyePoint = eyePoint; _previousLocalUp = localUp; _previousWidth = width; _previousHeight = height; _previousProjection = projection; _previousPosition = position; _matrixDirty = true; } if (_rotateInScreenSpace==true) { osg::Vec3d translation, scale; osg::Quat rotation, so; osg::RefMatrix& mvm = *(cv->getModelViewMatrix()); mvm.decompose( translation, rotation, scale, so ); // this will rotate the object into screen space. osg::Quat toScreen( rotation.inverse() ); // we need to compensate for the "heading" of the camera, so compute that. // From (http://goo.gl/9bjM4t). // GEOCENTRIC ONLY! const osg::Matrixd& view = cv->getCurrentCamera()->getViewMatrix(); osg::Matrixd viewInverse; viewInverse.invert(view); osg::Vec3d N(0, 0, 6356752); // north pole, more or less osg::Vec3d b( -view(0,2), -view(1,2), -view(2,2) ); // look vector osg::Vec3d E = osg::Vec3d(0,0,0)*viewInverse; osg::Vec3d u = E; u.normalize(); // account for looking straight downish if ( osg::equivalent(b*u, -1.0, 1e-4) ) { // up vec becomes the look vec. b = osg::Matrixd::transform3x3(view, osg::Vec3f(0.0,1.0,0.0)); b.normalize(); } osg::Vec3d proj_d = b - u*(b*u); osg::Vec3d n = N - E; osg::Vec3d proj_n = n - u*(n*u); osg::Vec3d proj_e = proj_n^u; double cameraHeading = atan2(proj_e*proj_d, proj_n*proj_d); //OE_NOTICE << "h=" << osg::RadiansToDegrees(cameraHeading) << std::endl; while (cameraHeading < 0.0) cameraHeading += osg::PI*2.0; double objHeading = _screenSpaceRotationRadians; while ( objHeading < 0.0 ) objHeading += osg::PI*2.0; double finalRot = cameraHeading - objHeading; while( finalRot > osg::PI ) finalRot -= osg::PI*2.0; osg::Quat toRotation( finalRot, osg::Vec3(0,0,1) ); setRotation( toRotation * toScreen ); } else if (_autoRotateMode==ROTATE_TO_SCREEN) { osg::Vec3d translation; osg::Quat rotation; osg::Vec3d scale; osg::Quat so; cv->getModelViewMatrix()->decompose( translation, rotation, scale, so ); setRotation(rotation.inverse()); } else if (_autoRotateMode==ROTATE_TO_CAMERA) { osg::Vec3d PosToEye = _position - eyePoint; osg::Matrix lookto = osg::Matrix::lookAt( osg::Vec3d(0,0,0), PosToEye, localUp); osg::Quat q; q.set(osg::Matrix::inverse(lookto)); setRotation(q); } else if (_autoRotateMode==ROTATE_TO_AXIS) { osg::Matrix matrix; osg::Vec3 ev(eyePoint - _position); switch(_cachedMode) { case(AXIAL_ROT_Z_AXIS): { ev.z() = 0.0f; float ev_length = ev.length(); if (ev_length>0.0f) { //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); float inv = 1.0f/ev_length; float s = ev.x()*inv; float c = -ev.y()*inv; matrix(0,0) = c; matrix(1,0) = -s; matrix(0,1) = s; matrix(1,1) = c; } break; } case(AXIAL_ROT_Y_AXIS): { ev.y() = 0.0f; float ev_length = ev.length(); if (ev_length>0.0f) { //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); float inv = 1.0f/ev_length; float s = -ev.z()*inv; float c = ev.x()*inv; matrix(0,0) = c; matrix(2,0) = s; matrix(0,2) = -s; matrix(2,2) = c; } break; } case(AXIAL_ROT_X_AXIS): { ev.x() = 0.0f; float ev_length = ev.length(); if (ev_length>0.0f) { //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); float inv = 1.0f/ev_length; float s = -ev.z()*inv; float c = -ev.y()*inv; matrix(1,1) = c; matrix(2,1) = -s; matrix(1,2) = s; matrix(2,2) = c; } break; } case(ROTATE_TO_AXIS): // need to implement { float ev_side = ev*_side; float ev_normal = ev*_normal; float rotation = atan2f(ev_side,ev_normal); matrix.makeRotate(rotation,_axis); break; } } osg::Quat q; q.set(matrix); setRotation(q); } _dirty = false; // update the LOD Scale based on the auto-scale. const double xScale = getScale().x(); if (xScale != 1.0 && xScale != 0.0) { oldLodScale = cv->getLODScale(); resetLodScale = true; cv->setLODScale( 1.0/xScale ); } } // if (cv) } // if is cull visitor // finally, skip AT's accept and do Transform. Transform::accept(nv); // Reset the LOD scale if we changed it if (resetLodScale) { osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv); if ( cv ) cv->setLODScale( oldLodScale ); } }