bool CullVisitor::updateCalculatedNearFar(const osg::Matrix& matrix,const osg::BoundingBox& bb) { // efficient computation of near and far, only taking into account the nearest and furthest // corners of the bounding box. value_type d_near = distance(bb.corner(_bbCornerNear),matrix); value_type d_far = distance(bb.corner(_bbCornerFar),matrix); if (d_near>d_far) { std::swap(d_near,d_far); if ( !EQUAL_F(d_near, d_far) ) { OSG_WARN<<"Warning: CullVisitor::updateCalculatedNearFar(.) near>far in range calculation,"<< std::endl; OSG_WARN<<" correcting by swapping values d_near="<<d_near<<" dfar="<<d_far<< std::endl; } } if (d_far<0.0) { // whole object behind the eye point so disguard return false; } if (d_near<_computed_znear) _computed_znear = d_near; if (d_far>_computed_zfar) _computed_zfar = d_far; return true; }
void TXPArchive::getExtents(osg::BoundingBox& extents) { TileInfo sw, ne; trpg2iPoint tileExtents; this->GetHeader()->GetLodSize(0, tileExtents); this->getTileInfo(0, 0, 0, sw); this->getTileInfo(tileExtents.x-1, tileExtents.y-1, 0, ne); extents.set(sw.bbox._min, sw.bbox._max); extents.expandBy(ne.bbox); }
osg::BoundingSphere TileNode::computeBound() const { osg::BoundingSphere bs; if (_surface.valid()) { bs = _surface->getBound(); const osg::BoundingBox bbox = _surface->getAlignedBoundingBox(); _tileKeyValue.a() = std::max( (bbox.xMax()-bbox.xMin()), (bbox.yMax()-bbox.yMin()) ); } return bs; }
double LispSM::calcNoptGeneral(const osg::Matrix lightSpace, const osg::BoundingBox &B_ls) const { const osg::Matrix &eyeView = getViewMatrix(); const osg::Matrix invLightSpace = osg::Matrix::inverse(lightSpace); const osg::Vec3d z0_ls = getZ0_ls(lightSpace, _E, B_ls.zMax(), getEyeDir()); const osg::Vec3d z1_ls = osg::Vec3d(z0_ls.x(), z0_ls.y(), B_ls.zMin()); // to world const osg::Vec4d z0_ws = osg::Vec4d(z0_ls, 1) * invLightSpace; const osg::Vec4d z1_ws = osg::Vec4d(z1_ls, 1) * invLightSpace; // to eye const osg::Vec4d z0_cs = z0_ws * eyeView; const osg::Vec4d z1_cs = z1_ws * eyeView; double z0 = -z0_cs.z() / z0_cs.w(); double z1 = -z1_cs.z() / z1_cs.w(); if (z1 / z0 <= 1.0) { // solve camera pos singularity in light space problem brutally: // if extreme points of B projected to Light space extend beyond // camera frustum simply use B extents in camera frustum // Its not optimal selection but ceratainly better than negative N osg::BoundingBox bb = _hull.computeBoundingBox(eyeView); z0 = -bb.zMax(); if (z0 <= 0) z0 = 0.1; z1 = -bb.zMin(); if (z1 <= z0) z1 = z0 + 0.1; } const double d = osg::absolute(B_ls.zMax() - B_ls.zMin()); double N = d / (sqrt(z1 / z0) - 1.0); #if PRINT_COMPUTED_N_OPT std::cout << " N=" << std::setw(8) << N << " n=" << std::setw(8) << z0 << " f=" << std::setw(8) << z1 << "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" << std::flush; #endif return N; }
void ComputeAABBOnBoneVisitor::serializeBoundingBox(const osg::BoundingBox &bb, const osg::Matrix &transform, osgAnimation::Bone &b, float ratio) { osg::Vec3 center = bb.center(); double halfLenghtX = (bb._max.x() - bb._min.x()) * 0.50; double halfLenghtY = (bb._max.y() - bb._min.y()) * 0.50; double halfLenghtZ = (bb._max.z() - bb._min.z()) * 0.50; halfLenghtX *= ratio; halfLenghtY *= ratio; halfLenghtZ *= ratio; osg::BoundingBox serializedBB; serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform); serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform); serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform); serializedBB.expandBy(osg::Vec3(center.x() - halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform); serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() + halfLenghtZ) * transform); serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() + halfLenghtY, center.z() - halfLenghtZ) * transform); serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() - halfLenghtZ) * transform); serializedBB.expandBy(osg::Vec3(center.x() + halfLenghtX, center.y() - halfLenghtY, center.z() + halfLenghtZ) * transform); b.setUserValue("AABBonBone_min", serializedBB._min); b.setUserValue("AABBonBone_max", serializedBB._max); }
void ComputeBoundsVisitor::applyBoundingBox(const osg::BoundingBox& bbox) { if (_matrixStack.empty()) _bb.expandBy(bbox); else if (bbox.valid()) { const osg::Matrix& matrix = _matrixStack.back(); _bb.expandBy(bbox.corner(0) * matrix); _bb.expandBy(bbox.corner(1) * matrix); _bb.expandBy(bbox.corner(2) * matrix); _bb.expandBy(bbox.corner(3) * matrix); _bb.expandBy(bbox.corner(4) * matrix); _bb.expandBy(bbox.corner(5) * matrix); _bb.expandBy(bbox.corner(6) * matrix); _bb.expandBy(bbox.corner(7) * matrix); } }
osg::Vec3 Curve::mapTo( const osg::Vec3 p, osg::BoundingBox originRect, osg::BoundingBox newRect ) { osg::Vec3 newPos = p-originRect.center(); osg::Vec3 originSpace = originRect._max-originRect._min; osg::Vec3 scaleFactor = (newRect._max-newRect._min); if ( originSpace.x() ) scaleFactor.x() /= originSpace.x(); else scaleFactor.x() = 0.0; if ( originSpace.y() ) scaleFactor.y() /= originSpace.y(); else scaleFactor.y() = 0.0; if ( originSpace.z() ) scaleFactor.z() /= originSpace.z(); else scaleFactor.z() = 0.0; newPos = osg::Vec3(newPos.x()*scaleFactor.x(), newPos.y()*scaleFactor.y(), newPos.z()*scaleFactor.z()); return newPos+newRect.center(); }
void Style::setupClipStateSet(const osg::BoundingBox& extents, osg::StateSet* stateset) { unsigned int clipTextureUnit = 1; stateset->setAttributeAndModes( new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.0f), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); stateset->setTextureAttributeAndModes( clipTextureUnit, _clipTexture.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); osg::Matrixd matrix = osg::Matrixd::translate(osg::Vec3(-extents.xMin(), -extents.yMin(), -extents.zMin()))* osg::Matrixd::scale(osg::Vec3(1.0f/(extents.xMax()-extents.xMin()), 1.0f/(extents.yMax()-extents.yMin()), 1.0f)); osg::ref_ptr<osg::TexGen> texgen = new osg::TexGen; texgen->setPlanesFromMatrix(matrix); texgen->setMode(osg::TexGen::OBJECT_LINEAR); stateset->setTextureAttributeAndModes( clipTextureUnit, texgen.get(), osg::StateAttribute::ON); }
BboxDrawable::BboxDrawable( const osg::BoundingBox& box, const BBoxSymbol &bboxSymbol ) : osg::Geometry() { setUseVertexBufferObjects(true); float margin = bboxSymbol.margin().isSet() ? bboxSymbol.margin().value() : 2.f; osg::Vec3Array* v = new osg::Vec3Array(); if ( bboxSymbol.geom().isSet() && bboxSymbol.geom().value() == BBoxSymbol::GEOM_BOX_ORIENTED ) { float h = box.yMax() - box.yMin() + 2.f * margin; v->push_back( osg::Vec3(box.xMax()+margin+h/2.f, box.yMax()+margin-h/2.f, 0) ); } v->push_back( osg::Vec3(box.xMax()+margin, box.yMax()+margin, 0) ); v->push_back( osg::Vec3(box.xMin()-margin, box.yMax()+margin, 0) ); v->push_back( osg::Vec3(box.xMin()-margin, box.yMin()-margin, 0) ); v->push_back( osg::Vec3(box.xMax()+margin, box.yMin()-margin, 0) ); setVertexArray(v); if ( v->getVertexBufferObject() ) v->getVertexBufferObject()->setUsage(GL_STATIC_DRAW_ARB); osg::Vec4Array* c = new osg::Vec4Array(); if ( bboxSymbol.fill().isSet() ) { c->push_back( bboxSymbol.fill()->color() ); addPrimitiveSet( new osg::DrawArrays(GL_POLYGON, 0, v->getNumElements()) ); } if ( bboxSymbol.border().isSet() ) { c->push_back( bboxSymbol.border()->color() ); if ( bboxSymbol.border()->width().isSet() ) getOrCreateStateSet()->setAttribute( new osg::LineWidth( bboxSymbol.border()->width().value() )); addPrimitiveSet( new osg::DrawArrays(GL_LINE_LOOP, 0, v->getNumElements()) ); } setColorArray( c ); setColorBinding( osg::Geometry::BIND_PER_PRIMITIVE_SET ); // add the static "isText=true" uniform; this is a hint for the annotation shaders // if they get installed. static osg::ref_ptr<osg::Uniform> s_isTextUniform = new osg::Uniform(osg::Uniform::BOOL, AnnotationUtils::UNIFORM_IS_TEXT()); s_isTextUniform->set( false ); getOrCreateStateSet()->addUniform( s_isTextUniform.get() ); // Disable culling since this bounding box will eventually be drawn in screen space. #if OSG_MIN_VERSION_REQUIRED(3,4,0) setCullingActive(false); #endif }
// this is the algorithm discussed in the article osg::Matrix LispSM::getLispSmMtx(const osg::Matrix &lightSpace) const { const osg::BoundingBox B_ls = _hull.computeBoundingBox(lightSpace); const double n = getN(lightSpace, B_ls); // get the coordinates of the near camera point in light space const osg::Vec3d e_ls = _E * lightSpace; // c start has the x and y coordinate of e, the z coord of B.min() const osg::Vec3d Cstart_lp(e_ls.x(), e_ls.y(), B_ls.zMax()); if (n >= OSG_INFINITY) { // if n is inf. than we should do uniform shadow mapping return osg::Matrix::identity(); } // calc C the projection center // new projection center C, n behind the near plane of P // we work along a negative axis so we transform +n*<the positive axis> == -n*<neg axis> const osg::Vec3d C(Cstart_lp + osg::Vec3d(0, 0, 1) * n); // construct a translation that moves to the projection center const osg::Matrix projectionCenter = osg::Matrix::translate(-C); // calc d the perspective transform depth or light space y extents const double d = osg::absolute(B_ls.zMax() - B_ls.zMin()); // the lispsm perspective transformation // here done with a standard frustum call that maps P onto the unit cube with // corner points [-1,-1,-1] and [1,1,1]. // in directX you can use the same mapping and do a mapping to the directX post-perspective cube // with corner points [-1,-1,0] and [1,1,1] as the final step after all the shadow mapping. osg::Matrix P = osg::Matrix::frustum(-1.0, 1.0, -1.0, 1.0, n, n + d); // invert the transform from right handed into left handed coordinate system for the ndc // done by the openGL style frustumGL call // so we stay in a right handed system P = P * osg::Matrix::scale(1.0, 1.0, -1.0); // return the lispsm frustum with the projection center return projectionCenter * P; }
void HorizonTileCuller::set(const osg::BoundingBox& bbox) { // Adjust the horizon ellipsoid based on the minimum Z value of the tile; // necessary because a tile that's below the ellipsoid (ocean floor, e.g.) // may be visible even if it doesn't pass the horizon-cone test. In such // cases we need a more conservative ellipsoid. double zMin = bbox.corner(0).z(); if ( zMin < 0.0 ) { _horizonProto.setEllipsoid( osg::EllipsoidModel(_radiusEquator + zMin, _radiusPolar + zMin) ); } // consider the uppermost 4 points of the tile-aligned bounding box. // (the last four corners of the bbox are the "zmax" corners.) for(unsigned i=0; i<4; ++i) { _points[i] = bbox.corner(4+i) * _local2world; } }
void ComputeBoundingBoxByRotation(osg::BoundingBox & InOut,osg::Vec3 BBCenter,float BBSize,osg::Matrixd Rotation) { osg::BoundingBox bb; bb.set(BBCenter.x()-BBSize,BBCenter.y()-BBSize,BBCenter.z()-BBSize,BBCenter.x()+BBSize,BBCenter.y()+BBSize,BBCenter.z()+BBSize); osg::BoundingBox Tbb; for(unsigned int i=0;i<8;i++) { Tbb.expandBy(Rotation.preMult(bb.corner(i))); } InOut.set(Tbb.xMin(),Tbb.yMin(),Tbb.zMin(),Tbb.xMax(),Tbb.yMax(),Tbb.zMax()); }
BboxDrawable::BboxDrawable( const osg::BoundingBox& box, const BBoxSymbol &bboxSymbol ) : osg::Geometry() { setUseVertexBufferObjects(true); float margin = bboxSymbol.margin().isSet() ? bboxSymbol.margin().value() : 2.f; osg::Vec3Array* v = new osg::Vec3Array(); if ( bboxSymbol.geom().isSet() && bboxSymbol.geom().value() == BBoxSymbol::GEOM_BOX_ORIENTED ) { float h = box.yMax() - box.yMin() + 2.f * margin; v->push_back( osg::Vec3(box.xMax()+margin+h/2.f, box.yMax()+margin-h/2.f, 0) ); } v->push_back( osg::Vec3(box.xMax()+margin, box.yMax()+margin, 0) ); v->push_back( osg::Vec3(box.xMin()-margin, box.yMax()+margin, 0) ); v->push_back( osg::Vec3(box.xMin()-margin, box.yMin()-margin, 0) ); v->push_back( osg::Vec3(box.xMax()+margin, box.yMin()-margin, 0) ); setVertexArray(v); if ( v->getVertexBufferObject() ) v->getVertexBufferObject()->setUsage(GL_STATIC_DRAW_ARB); osg::Vec4Array* c = new osg::Vec4Array(osg::Array::BIND_PER_PRIMITIVE_SET); if ( bboxSymbol.fill().isSet() ) { c->push_back( bboxSymbol.fill()->color() ); osg::DrawElements* de = new osg::DrawElementsUByte(GL_TRIANGLE_STRIP); de->addElement(0); de->addElement(1); de->addElement(3); de->addElement(2); addPrimitiveSet(de); //addPrimitiveSet( new osg::DrawArrays(GL_POLYGON, 0, v->getNumElements()) ); } if ( bboxSymbol.border().isSet() ) { c->push_back( bboxSymbol.border()->color() ); if ( bboxSymbol.border()->width().isSet() ) getOrCreateStateSet()->setAttribute( new osg::LineWidth( bboxSymbol.border()->width().value() )); addPrimitiveSet( new osg::DrawArrays(GL_LINE_LOOP, 0, v->getNumElements()) ); } setColorArray( c ); // Disable culling since this bounding box will eventually be drawn in screen space. setCullingActive(false); }
void BuildKdTree::computeDivisions(KdTree::BuildOptions& options) { osg::Vec3 dimensions(_bb.xMax()-_bb.xMin(), _bb.yMax()-_bb.yMin(), _bb.zMax()-_bb.zMin()); #ifdef VERBOSE_OUTPUT OSG_NOTICE<<"computeDivisions("<<options._maxNumLevels<<") "<<dimensions<< " { "<<std::endl; #endif _axisStack.reserve(options._maxNumLevels); for(unsigned int level=0; level<options._maxNumLevels; ++level) { int axis = 0; if (dimensions[0]>=dimensions[1]) { if (dimensions[0]>=dimensions[2]) axis = 0; else axis = 2; } else if (dimensions[1]>=dimensions[2]) axis = 1; else axis = 2; _axisStack.push_back(axis); dimensions[axis] /= 2.0f; #ifdef VERBOSE_OUTPUT OSG_NOTICE<<" "<<level<<", "<<dimensions<<", "<<axis<<std::endl; #endif } #ifdef VERBOSE_OUTPUT OSG_NOTICE<<"}"<<std::endl; #endif }
void apply(osg::Node &node) { osg::Transform *mt; osg::Geode *geo; osg::ref_ptr<osg::RefMatrix> M = matStack.back(); if ((geo = dynamic_cast<osg::Geode *>(&node))) { unsigned int i; osg::BoundingBox bb; for (i = 0; i < geo->getNumDrawables(); i++) { bb.expandBy(geo->getDrawable(i)->getBound()); } if (M.get()) { bbox.expandBy(osg::Vec3(bb.xMin(), bb.yMin(), bb.zMin()) * *M); bbox.expandBy(osg::Vec3(bb.xMax(), bb.yMax(), bb.zMax()) * *M); } else { bbox.expandBy(osg::Vec3(bb.xMin(), bb.yMin(), bb.zMin())); bbox.expandBy(osg::Vec3(bb.xMax(), bb.yMax(), bb.zMax())); } } if ((mt = dynamic_cast<osg::Transform *>(&node))) { osg::ref_ptr<osg::RefMatrix> matrix = new osg::RefMatrix; mt->computeLocalToWorldMatrix(*matrix, this); matStack.push_back(matrix); } traverse(node); if ((mt = dynamic_cast<osg::Transform *>(&node))) { matStack.pop_back(); } }
void HorizonTileCuller::set(const SpatialReference* srs, const osg::Matrix& local2world, const osg::BoundingBox& bbox) { if (!_horizon.valid() && srs->isGeographic()) { _horizon = new Horizon(); } if (_horizon.valid()) { _horizon->setEllipsoid(*srs->getEllipsoid()); //_radiusPolar = srs->getEllipsoid()->getRadiusPolar(); //_radiusEquator = srs->getEllipsoid()->getRadiusEquator(); //_local2world = local2world; // Adjust the horizon ellipsoid based on the minimum Z value of the tile; // necessary because a tile that's below the ellipsoid (ocean floor, e.g.) // may be visible even if it doesn't pass the horizon-cone test. In such // cases we need a more conservative ellipsoid. double zMin = (double)std::min( bbox.corner(0).z(), 0.0f ); zMin = std::max(zMin, -25000.0); // approx the lowest point on earth * 2 _horizon->setEllipsoid( osg::EllipsoidModel( srs->getEllipsoid()->getRadiusEquator() + zMin, srs->getEllipsoid()->getRadiusPolar() + zMin) ); // consider the uppermost 4 points of the tile-aligned bounding box. // (the last four corners of the bbox are the "zmax" corners.) for(unsigned i=0; i<4; ++i) { _points[i] = bbox.corner(4+i) * local2world; } //_bs.set(bbox.center() * _local2world, bbox.radius()); } }
bool DebugShadowMap::ViewData::DebugBoundingBox ( const osg::BoundingBox & bb, const char * name ) { bool result = false; #if defined( _DEBUG ) || defined( DEBUG ) if( !name ) name = ""; osg::BoundingBox & bb_prev = _boundingBoxMap[ std::string( name ) ]; result = bb.center() != bb_prev.center() || bb.radius() != bb_prev.radius(); if( result ) std::cout << "Box<" << name << "> (" << ( bb._max._v[0] + bb._min._v[0] ) * 0.5 << " " << ( bb._max._v[1] + bb._min._v[1] ) * 0.5 << " " << ( bb._max._v[2] + bb._min._v[2] ) * 0.5 << ") [" << ( bb._max._v[0] - bb._min._v[0] ) << " " << ( bb._max._v[1] - bb._min._v[1] ) << " " << ( bb._max._v[2] - bb._min._v[2] ) << "] " << std::endl; bb_prev = bb; #endif return result; }
bool GetBoundingBox(osg::BoundingBox & BB, dtCore::DeltaDrawable & drawable) { osg::Node* node = drawable.GetOSGNode(); if (node != 0) { dtUtil::BoundingBoxVisitor bbv; node->accept(bbv); // no copy constructor for osg::BB... BB.set(bbv.mBoundingBox._min, bbv.mBoundingBox._max); return true; } LOG_WARNING("No valid osg node of drawable when asking for bounding box."); return false; }
inline bool CheckAndMultiplyBoxIfWithinPolytope ( osg::BoundingBox & bb, osg::Matrix & m, osg::Polytope &p ) { if( !bb.valid() ) return false; osg::Vec3 o = bb._min * m, s[3]; for( int i = 0; i < 3; i ++ ) s[i] = osg::Vec3( m(i,0), m(i,1), m(i,2) ) * ( bb._max[i] - bb._min[i] ); for( osg::Polytope::PlaneList::iterator it = p.getPlaneList().begin(); it != p.getPlaneList().end(); ++it ) { float dist = it->distance( o ), dist_min = dist, dist_max = dist; for( int i = 0; i < 3; i ++ ) { dist = it->dotProductNormal( s[i] ); if( dist < 0 ) dist_min += dist; else dist_max += dist; } if( dist_max < 0 ) return false; } bb._max = bb._min = o; #if 1 for( int i = 0; i < 3; i ++ ) for( int j = 0; j < 3; j ++ ) if( s[i][j] < 0 ) bb._min[j] += s[i][j]; else bb._max[j] += s[i][j]; #else b.expandBy( o + s[0] ); b.expandBy( o + s[1] ); b.expandBy( o + s[2] ); b.expandBy( o + s[0] + s[1] ); b.expandBy( o + s[0] + s[2] ); b.expandBy( o + s[1] + s[2] ); b.expandBy( o + s[0] + s[1] + s[2] ); #endif #if ( IGNORE_OBJECTS_LARGER_THAN_HEIGHT > 0 ) if( bb._max[2] - bb._min[2] > IGNORE_OBJECTS_LARGER_THAN_HEIGHT ) // ignore huge objects return false; #endif return true; }
void MinimalShadowMap::ViewData::cutScenePolytope ( const osg::Matrix & transform, const osg::Matrix & inverse, const osg::BoundingBox & bb ) { _sceneReceivingShadowPolytopePoints.clear(); if( bb.valid() ) { osg::Polytope polytope; polytope.setToBoundingBox( bb ); polytope.transformProvidingInverse( inverse ); _sceneReceivingShadowPolytope.cut( polytope ); _sceneReceivingShadowPolytope.getPoints ( _sceneReceivingShadowPolytopePoints ); } else _sceneReceivingShadowPolytope.clear(); }
CSulGeomBox::CSulGeomBox( const osg::BoundingBox& bb ) : CSulGeode() { m_minX = bb.xMin(); m_maxX = bb.xMax(); m_minY = bb.yMin(); m_maxY = bb.yMax(); m_minZ = bb.zMin(); m_maxZ = bb.zMax(); createDrawable(); }
bool PickEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv) { if (ea.getHandled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::MOVE): case(osgGA::GUIEventAdapter::PUSH): case(osgGA::GUIEventAdapter::DRAG): case(osgGA::GUIEventAdapter::RELEASE): { if(ea.getEventType() == osgGA::GUIEventAdapter::PUSH) { _drawablesOnPush.clear(); } osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa); osgUtil::LineSegmentIntersector::Intersections intersections; if (viewer->computeIntersections(ea, nv->getNodePath(), intersections)) { for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr=intersections.begin(); hitr!=intersections.end(); ++hitr) { if (_operation == FORWARD_MOUSE_EVENT) { osg::ref_ptr<osgGA::GUIEventAdapter> cloned_ea = osg::clone(&ea); // clear touch-data as this prevents sending the event as mouse-event cloned_ea->setTouchData(NULL); // reproject mouse-coord const osg::BoundingBox bb(hitr->drawable->getBound()); const osg::Vec3& p(hitr->localIntersectionPoint); float transformed_x = (p.x() - bb.xMin()) / (bb.xMax() - bb.xMin()); float transformed_y = (p.z() - bb.zMin()) / (bb.zMax() - bb.zMin()); cloned_ea->setX(ea.getXmin() + transformed_x * (ea.getXmax() - ea.getXmin())); cloned_ea->setY(ea.getYmin() + transformed_y * (ea.getYmax() - ea.getYmin())); cloned_ea->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); // std::cout << transformed_x << "/" << transformed_x << " -> " << cloned_ea->getX() << "/" <<cloned_ea->getY() << std::endl; SlideEventHandler::instance()->forwardEventToDevices(cloned_ea.get()); } else if ((_operation == FORWARD_TOUCH_EVENT) && ea.isMultiTouchEvent()) { osg::ref_ptr<osgGA::GUIEventAdapter> cloned_ea = osg::clone(&ea); cloned_ea->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS); osgGA::GUIEventAdapter::TouchData* touch_data = cloned_ea->getTouchData(); // reproject touch-points const osg::BoundingBox bb(hitr->drawable->getBound()); osg::Camera* camera = viewer->getCamera(); osg::Matrix matrix = osg::computeLocalToWorld(hitr->nodePath, false) * camera->getViewMatrix() * camera->getProjectionMatrix(); matrix.postMult(camera->getViewport()->computeWindowMatrix()); osg::Matrixd inverse; inverse.invert(matrix); // transform touch-points into local coord-system unsigned int j(0); for(osgGA::GUIEventAdapter::TouchData::iterator i = touch_data->begin(); i != touch_data->end(); ++i, ++j) { osg::Vec3 local = osg::Vec3(i->x, i->y, 0) * inverse; // std::cout << local << " hit: " << hitr->localIntersectionPoint << std::endl; local.x() = (local.x() - bb.xMin()) / (bb.xMax() - bb.xMin()); local.z() = (local.z() - bb.zMin()) / (bb.zMax() - bb.zMin()); local.x() = (ea.getXmin() + local.x() * (ea.getXmax() - ea.getXmin())); local.z() = (ea.getYmin() + local.z() * (ea.getYmax() - ea.getYmin())); // std::cout << ea.getX() << "/" << ea.getY() << " -- " << i->x << " " << i->y << " -> " << local.x() <<"/" << local.z() << std::endl; i->x = local.x(); i->y = 1 + local.z(); // no idea why I have to add 1 to get y in the range [0..1] } // std::cout << transformed_x << "/" << transformed_x << " -> " << cloned_ea->getX() << "/" <<cloned_ea->getY() << std::endl; SlideEventHandler::instance()->forwardEventToDevices(cloned_ea.get()); } else { if (ea.getEventType()==osgGA::GUIEventAdapter::PUSH) { _drawablesOnPush.insert( hitr->drawable.get() ); } else if (ea.getEventType()==osgGA::GUIEventAdapter::MOVE) { OSG_INFO<<"Tooltip..."<<std::endl; } else if (ea.getEventType()==osgGA::GUIEventAdapter::RELEASE) { if (_drawablesOnPush.find(hitr->drawable.get()) != _drawablesOnPush.end()) doOperation(); return true; } } } } break; } case(osgGA::GUIEventAdapter::KEYDOWN): { //OSG_NOTICE<<"PickEventHandler KEYDOWN "<<(char)ea.getKey()<<std::endl; //if (object) OSG_NOTICE<<" "<<object->className()<<std::endl; break; } default: break; } return false; }
inline void init_towbar() { body_s_ = findFirstNode((tow_visual_object_)->root(),"body_s"); body_b_ = findFirstNode((tow_visual_object_)->root(),"body_b"); body_a_ = findFirstNode((tow_visual_object_)->root(),"body_a"); osg::ComputeBoundsVisitor cbvs; body_s_->accept( cbvs ); const osg::BoundingBox bb_s = cbvs.getBoundingBox(); osg::ComputeBoundsVisitor cbvb; body_b_->accept( cbvb ); const osg::BoundingBox bb_b = cbvb.getBoundingBox(); osg::ComputeBoundsVisitor cbva; body_a_->accept( cbva ); const osg::BoundingBox bb_a = cbva.getBoundingBox(); osg::ComputeBoundsVisitor cbv; (tow_visual_object_)->root()->accept( cbv ); const osg::BoundingBox bb_ = cbv.getBoundingBox(); radius_ = abs(bb_.yMax() - bb_.yMin())/2.0;//(*tow_visual_object_)->root()->getBound().radius(); radius_s_ = abs(bb_s.yMax() - bb_s.yMin())/2.0;//body_s_->getBound().radius(); radius_a_ = abs(bb_a.yMax() - bb_a.yMin())/2.0;//body_a_->getBound().radius(); radius_b_ = abs(bb_b.yMax() - bb_b.yMin())/2.0;//body_b_->getBound().radius(); }
bool PickEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv) { if (ea.getHandled()) return false; switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::MOVE): case(osgGA::GUIEventAdapter::PUSH): case(osgGA::GUIEventAdapter::DRAG): case(osgGA::GUIEventAdapter::RELEASE): { if(ea.getEventType() == osgGA::GUIEventAdapter::PUSH) { _drawablesOnPush.clear(); } osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa); osgUtil::LineSegmentIntersector::Intersections intersections; if (viewer->computeIntersections(ea, nv->getNodePath(), intersections)) { for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr=intersections.begin(); hitr!=intersections.end(); ++hitr) { if (_operation == FORWARD_EVENT) { osg::ref_ptr<osgGA::GUIEventAdapter> cloned_ea = osg::clone(&ea); const osg::BoundingBox bb(hitr->drawable->getBound()); const osg::Vec3& p(hitr->localIntersectionPoint); float transformed_x = (p.x() - bb.xMin()) / (bb.xMax() - bb.xMin()); float transformed_y = (p.z() - bb.zMin()) / (bb.zMax() - bb.zMin()); cloned_ea->setX(ea.getXmin() + transformed_x * (ea.getXmax() - ea.getXmin())); cloned_ea->setY(ea.getYmin() + transformed_y * (ea.getYmax() - ea.getYmin())); cloned_ea->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS); // std::cout << transformed_x << "/" << transformed_x << " -> " << cloned_ea->getX() << "/" <<cloned_ea->getY() << std::endl; // dispatch cloned event to devices osgViewer::View::Devices& devices = viewer->getDevices(); for(osgViewer::View::Devices::iterator i = devices.begin(); i != devices.end(); ++i) { if((*i)->getCapabilities() & osgGA::Device::SEND_EVENTS) { (*i)->sendEvent(*cloned_ea); } } } else { if (ea.getEventType()==osgGA::GUIEventAdapter::PUSH) { _drawablesOnPush.insert( hitr->drawable.get() ); } else if (ea.getEventType()==osgGA::GUIEventAdapter::MOVE) { OSG_INFO<<"Tooltip..."<<std::endl; } else if (ea.getEventType()==osgGA::GUIEventAdapter::RELEASE) { if (_drawablesOnPush.find(hitr->drawable.get()) != _drawablesOnPush.end()) doOperation(); return true; } } } } break; } case(osgGA::GUIEventAdapter::KEYDOWN): { //OSG_NOTICE<<"PickEventHandler KEYDOWN "<<(char)ea.getKey()<<std::endl; //if (object) OSG_NOTICE<<" "<<object->className()<<std::endl; break; } default: break; } return false; }
void MxCore::lookAtAndFit( const osg::BoundingBox& bb ) { // We'll get the view matrix to project the bounding box, so pre-configure it // to point at the box center. Eye position doesn't matter at this point (we // compute the eye position at the end of the function). osg::Vec3d newDir = bb.center() - _position; newDir.normalize(); setDir( newDir ); // Ttransform the bounding box vertices into eye space, // then determine their x and y extents. We'll compare the eye // space bb aspect ratio against the projection _aspect to // determine the critical axis to fit. osg::ref_ptr< osg::Vec3Array > corners = new osg::Vec3Array; corners->resize( 8 ); ( *corners )[ 0 ].set( bb._min ); ( *corners )[ 1 ].set( bb._max.x(), bb._min.y(), bb._min.z() ); ( *corners )[ 2 ].set( bb._max.x(), bb._min.y(), bb._max.z() ); ( *corners )[ 3 ].set( bb._min.x(), bb._min.y(), bb._max.z() ); ( *corners )[ 4 ].set( bb._max ); ( *corners )[ 5 ].set( bb._min.x(), bb._max.y(), bb._max.z() ); ( *corners )[ 6 ].set( bb._min.x(), bb._max.y(), bb._min.z() ); ( *corners )[ 7 ].set( bb._max.x(), bb._max.y(), bb._min.z() ); osgwTools::transform( getInverseMatrix(), corners.get() ); // The 'corners' array of bb verts are now in eye space. // Determine max and min values for eye space x and y osg::Vec2 minEC( FLT_MAX, FLT_MAX ), maxEC( FLT_MIN, FLT_MIN ); unsigned int idx; for( idx=0; idx<8; idx++ ) { const osg::Vec3& v( ( *corners )[ idx ] ); minEC[ 0 ] = osg::minimum< float >( v.x(), minEC[ 0 ] ); minEC[ 1 ] = osg::minimum< float >( v.y(), minEC[ 1 ] ); maxEC[ 0 ] = osg::maximum< float >( v.x(), maxEC[ 0 ] ); maxEC[ 1 ] = osg::maximum< float >( v.y(), maxEC[ 1 ] ); } // aspect is width (x) over height (y). const double ecWidth( maxEC[ 0 ] - minEC[ 0 ] ); const double ecHeight( maxEC[ 1 ] - minEC[ 1 ] ); const double ecAspect = ecWidth / ecHeight; // We'll store half the extent of interest into a dummy bounding sphere's radius. // We'll store the analogous fov in bestFov. osg::BoundingSphere bs; double bestFov; if( ecAspect > _aspect ) { // Fit eye space x to the view bs.radius() = ecWidth * .5; bestFov = _aspect * _fovy; } else { // Fit eye space y to the view bs.radius() = ecHeight * .5; bestFov = _fovy; } // The wrap-up code sets the eye position at the best distance from // the bb center. Extra distance is added in to account for the fact // that the input bound probably has a larger radius than the eye coord // bound that we're passing to computeInitialDistanceFromFOVY(). const double extraDistance = bb.radius() - bs.radius(); const double distance = extraDistance + osgwMx::computeInitialDistanceFromFOVY( bs, bestFov ); setPosition( bs.center() - ( newDir * distance ) ); }
void WriterCompareTriangle::cutscene(int nbVertices, const osg::BoundingBox& sceneBox) { osg::BoundingBox::vec_type length = sceneBox._max - sceneBox._min; static const unsigned int k = 4; unsigned int nbVerticesX = (nbVertices * k) / (length.z() * length.y()); unsigned int nbVerticesY = (nbVertices * k) / (length.z() * length.x()); unsigned int nbVerticesZ = (nbVertices * k) / (length.x() * length.y()); setMaxMin (nbVerticesX, nbVerticesY, nbVerticesZ); OSG_DEBUG << "Cutting x by " << nbVerticesX << std::endl << "Cutting y by " << nbVerticesY << std::endl << "Cutting z by " << nbVerticesZ << std::endl; osg::BoundingBox::value_type blocX = length.x() / nbVerticesX; //These 3 lines set the size of a box in x, y and z osg::BoundingBox::value_type blocY = length.y() / nbVerticesY; osg::BoundingBox::value_type blocZ = length.z() / nbVerticesZ; boxList.reserve(nbVerticesX * nbVerticesY * nbVerticesZ); short yinc = 1; short xinc = 1; unsigned int y = 0; unsigned int x = 0; for (unsigned int z = 0; z < nbVerticesZ; ++z) { while (x < nbVerticesX && x >= 0) { while (y < nbVerticesY && y >= 0) { osg::BoundingBox::value_type xMin = sceneBox.xMin() + x * blocX; if (x == 0) //to prevent from mesh with no case xMin -= 10; osg::BoundingBox::value_type yMin = sceneBox.yMin() + y * blocY; if (y == 0) //to prevent from mesh with no case yMin -= 10; osg::BoundingBox::value_type zMin = sceneBox.zMin() + z * blocZ; if (z == 0) //to prevent from mesh with no case zMin -= 10; osg::BoundingBox::value_type xMax = sceneBox.xMin() + (x + 1) * blocX; if (x == nbVerticesX - 1) //to prevent from mesh with no case xMax += 10; osg::BoundingBox::value_type yMax = sceneBox.yMin() + (y + 1) * blocY; if (y == nbVerticesY - 1) //to prevent from mesh with no case yMax += 10; osg::BoundingBox::value_type zMax = sceneBox.zMin() + (z + 1) * blocZ; if (z == nbVerticesZ - 1) //to prevent from mesh with no case zMax += 10; boxList.push_back(osg::BoundingBox(xMin, // Add a box to the list yMin, zMin, xMax, yMax, zMax)); y += yinc; } yinc = -yinc; y += yinc; x += xinc; } xinc = -xinc; x += xinc; } }
bool IntersectKdTree::intersectAndClip(osg::Vec3& s, osg::Vec3& e, const osg::BoundingBox& bb) const { //return true; //if (!bb.valid()) return true; // compate s and e against the xMin to xMax range of bb. if (s.x()<=e.x()) { // trivial reject of segment wholely outside. if (e.x()<bb.xMin()) return false; if (s.x()>bb.xMax()) return false; if (s.x()<bb.xMin()) { // clip s to xMin. s = s+_d_invX*(bb.xMin()-s.x()); } if (e.x()>bb.xMax()) { // clip e to xMax. e = s+_d_invX*(bb.xMax()-s.x()); } } else { if (s.x()<bb.xMin()) return false; if (e.x()>bb.xMax()) return false; if (e.x()<bb.xMin()) { // clip s to xMin. e = s+_d_invX*(bb.xMin()-s.x()); } if (s.x()>bb.xMax()) { // clip e to xMax. s = s+_d_invX*(bb.xMax()-s.x()); } } // compate s and e against the yMin to yMax range of bb. if (s.y()<=e.y()) { // trivial reject of segment wholely outside. if (e.y()<bb.yMin()) return false; if (s.y()>bb.yMax()) return false; if (s.y()<bb.yMin()) { // clip s to yMin. s = s+_d_invY*(bb.yMin()-s.y()); } if (e.y()>bb.yMax()) { // clip e to yMax. e = s+_d_invY*(bb.yMax()-s.y()); } } else { if (s.y()<bb.yMin()) return false; if (e.y()>bb.yMax()) return false; if (e.y()<bb.yMin()) { // clip s to yMin. e = s+_d_invY*(bb.yMin()-s.y()); } if (s.y()>bb.yMax()) { // clip e to yMax. s = s+_d_invY*(bb.yMax()-s.y()); } } // compate s and e against the zMin to zMax range of bb. if (s.z()<=e.z()) { // trivial reject of segment wholely outside. if (e.z()<bb.zMin()) return false; if (s.z()>bb.zMax()) return false; if (s.z()<bb.zMin()) { // clip s to zMin. s = s+_d_invZ*(bb.zMin()-s.z()); } if (e.z()>bb.zMax()) { // clip e to zMax. e = s+_d_invZ*(bb.zMax()-s.z()); } } else { if (s.z()<bb.zMin()) return false; if (e.z()>bb.zMax()) return false; if (e.z()<bb.zMin()) { // clip s to zMin. e = s+_d_invZ*(bb.zMin()-s.z()); } if (s.z()>bb.zMax()) { // clip e to zMax. s = s+_d_invZ*(bb.zMax()-s.z()); } } // OSG_NOTICE<<"clampped segment "<<s<<" "<<e<<std::endl; // if (s==e) return false; return true; }
void WriterCompareTriangle::cutscene(int nbVertices, const osg::BoundingBox & sceneBox) { osg::BoundingBox::vec_type length = sceneBox._max - sceneBox._min; static const float k = 1.3f; // Arbitrary constant multiplier for density computation ("simulates" non-uniform point distributions) // Computes "density" of points, and thus the number of blocks to divide the mesh into int nbVerticesX = static_cast<int>( (nbVertices * k) / (length.z() * length.y()) ); int nbVerticesY = static_cast<int>( (nbVertices * k) / (length.z() * length.x()) ); int nbVerticesZ = static_cast<int>( (nbVertices * k) / (length.x() * length.y()) ); setMaxMin (nbVerticesX, nbVerticesY, nbVerticesZ); // This function prevent from cutting the scene in too many blocs OSG_INFO << "Cutting x by " << nbVerticesX << std::endl << "Cutting y by " << nbVerticesY << std::endl << "Cutting z by " << nbVerticesZ << std::endl; osg::BoundingBox::value_type blocX = length.x() / nbVerticesX; // These 3 lines set the size of a bloc in x, y and z osg::BoundingBox::value_type blocY = length.y() / nbVerticesY; osg::BoundingBox::value_type blocZ = length.z() / nbVerticesZ; boxList.reserve(nbVerticesX * nbVerticesY * nbVerticesZ); short yinc = 1; short xinc = 1; int y = 0; int x = 0; for (int z = 0; z < nbVerticesZ; ++z) { while (x < nbVerticesX && x >= 0) { while (y < nbVerticesY && y >= 0) { osg::BoundingBox::value_type xMin = sceneBox.xMin() + x * blocX; if (x == 0) //to prevent from mesh with no case xMin -= 10; osg::BoundingBox::value_type yMin = sceneBox.yMin() + y * blocY; if (y == 0) //to prevent from mesh with no case yMin -= 10; osg::BoundingBox::value_type zMin = sceneBox.zMin() + z * blocZ; if (z == 0) //to prevent from mesh with no case zMin -= 10; osg::BoundingBox::value_type xMax = sceneBox.xMin() + (x + 1) * blocX; if (x == nbVerticesX - 1) //to prevent from mesh with no case xMax += 10; osg::BoundingBox::value_type yMax = sceneBox.yMin() + (y + 1) * blocY; if (y == nbVerticesY - 1) //to prevent from mesh with no case yMax += 10; osg::BoundingBox::value_type zMax = sceneBox.zMin() + (z + 1) * blocZ; if (z == nbVerticesZ - 1) //to prevent from mesh with no case zMax += 10; boxList.push_back(osg::BoundingBox(xMin, // Add a bloc to the list yMin, zMin, xMax, yMax, zMax)); y += yinc; } yinc = -yinc; y += yinc; x += xinc; } xinc = -xinc; x += xinc; } }
void MinimalShadowMap::ViewData::trimProjection ( osg::Matrixd & projectionMatrix, osg::BoundingBox bb, unsigned int trimMask ) { #if 1 if( !bb.valid() || !( trimMask & (1|2|4|8|16|32) ) ) return; double l = -1, r = 1, b = -1, t = 1, n = 1, f = -1; #if 0 // make sure bounding box does not extend beyond unit frustum clip range for( int i = 0; i < 3; i ++ ) { if( bb._min[i] < -1 ) bb._min[i] = -1; if( bb._max[i] > 1 ) bb._max[i] = 1; } #endif if( trimMask & 1 ) l = bb._min[0]; if( trimMask & 2 ) r = bb._max[0]; if( trimMask & 4 ) b = bb._min[1]; if( trimMask & 8 ) t = bb._max[1]; if( trimMask & 16 ) n = -bb._min[2]; if( trimMask & 32 ) f = -bb._max[2]; projectionMatrix.postMult( osg::Matrix::ortho( l,r,b,t,n,f ) ); #else if( !bb.valid() || !( trimMask & (1|2|4|8|16|32) ) ) return; double l, r, t, b, n, f; bool ortho = projectionMatrix.getOrtho( l, r, b, t, n, f ); if( !ortho && !projectionMatrix.getFrustum( l, r, b, t, n, f ) ) return; // rotated or skewed or other crooked projection - give up // make sure bounding box does not extend beyond unit frustum clip range for( int i = 0; i < 3; i ++ ) { if( bb._min[i] < -1 ) bb._min[i] = -1; if( bb._max[i] > 1 ) bb._max[i] = 1; } osg::Matrix projectionToView = osg::Matrix::inverse( projectionMatrix ); osg::Vec3 min = osg::Vec3( bb._min[0], bb._min[1], bb._min[2] ) * projectionToView; osg::Vec3 max = osg::Vec3( bb._max[0], bb._max[1], bb._max[2] ) * projectionToView; if( trimMask & 16 ) { // trim near if( !ortho ) { // recalc frustum corners on new near plane l *= -min[2] / n; r *= -min[2] / n; b *= -min[2] / n; t *= -min[2] / n; } n = -min[2]; } if( trimMask & 32 ) // trim far f = -max[2]; if( !ortho ) { min[0] *= -n / min[2]; min[1] *= -n / min[2]; max[0] *= -n / max[2]; max[1] *= -n / max[2]; } if( l < r ) { // check for inverted X range if( l < min[0] && ( trimMask & 1 ) ) l = min[0]; if( r > max[0] && ( trimMask & 2 ) ) r = max[0]; } else { if( l > min[0] && ( trimMask & 1 ) ) l = min[0]; if( r < max[0] && ( trimMask & 2 ) ) r = max[0]; } if( b < t ) { // check for inverted Y range if( b < min[1] && ( trimMask & 4 ) ) b = min[1]; if( t > max[1] && ( trimMask & 8 ) ) t = max[1]; } else { if( b > min[1] && ( trimMask & 4 ) ) b = min[1]; if( t < max[1] && ( trimMask & 8 ) ) t = max[1]; } if( ortho ) projectionMatrix.makeOrtho( l, r, b, t, n, f ); else projectionMatrix.makeFrustum( l, r, b, t, n, f ); #endif }
osg::ref_ptr<osg::Geometry> HUDView::createRandNumBackground(osg::BoundingBox bb) { osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; osg::Vec3 sizeUpY(0, bb.yMax() + bb.yMax() / 2, 0.0); osg::Vec3 sizeUpYN(0, -bb.yMax() / 2, 0.0); bb.expandBy(sizeUpY); bb.expandBy(sizeUpYN); osg::Vec3 halfExtent((bb.xMax() - bb.xMin()) / 2.0, (bb.yMax() - bb.yMin()) / 2.0f, 0); float x_length = bb.xMax() - bb.xMin(); float y_length = bb.yMax() - bb.yMin(); vertices->push_back(osg::Vec3(0, y_length, 0) - halfExtent); vertices->push_back(osg::Vec3(0, 0, 0) - halfExtent); vertices->push_back(osg::Vec3(x_length, 0, 0) - halfExtent); vertices->push_back(osg::Vec3(x_length, y_length, 0) - halfExtent); geom->setVertexArray(vertices); osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array; normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f)); geom->setNormalArray(normals, osg::Array::BIND_OVERALL); osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; colors->push_back(osg::Vec4(0.0f, 0.2f, 1.0f, 0.7f)); geom->setColorArray(colors, osg::Array::BIND_OVERALL); geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4)); osg::ref_ptr<osg::StateSet> stateset = geom->getOrCreateStateSet(); stateset->setMode(GL_BLEND, osg::StateAttribute::ON); stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); //stateset->setAttribute(new osg::PolygonOffset(1.0f,1.0f),osg::StateAttribute::ON); stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); return geom; }