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 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 }
// 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; }
osg::Vec2 Curve::mapTo2D( const osg::Vec3 p, osg::BoundingBox originRect, osg::BoundingBox newRect ) { if ( originRect.xMin()==originRect.xMax() ) { newRect.zMin() = newRect.yMin(); newRect.zMax() = newRect.yMax(); newRect.yMin() = newRect.xMin(); newRect.yMax() = newRect.xMax(); newRect.xMin() = 0.0; newRect.xMax() = 0.0; } else if ( originRect.yMin()==originRect.yMax() ) { newRect.zMin() = newRect.yMin(); newRect.zMax() = newRect.yMax(); newRect.yMin() = 0.0; newRect.yMax() = 0.0; } osg::Vec3 newPoint = mapTo( p, originRect, newRect ); osg::Vec2 point2D( newPoint.x(), newPoint.y() ); if ( originRect.xMin()==originRect.xMax() ) point2D.set( newPoint.y(), newPoint.z() ); else if ( originRect.yMin()==originRect.yMax() ) point2D.set( newPoint.x(), newPoint.z() ); return point2D; }
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; }
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; }
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 doQuadTreeVPB(std::string basePath,std::vector<std::vector<string> > datalist_lod,Bounds bounds,CameraCalib &calib,texcache_t cachedDirs,int POTAtlasSize,bool useTextureArray,bool useReimage,bool useVirtualTex,const osg::BoundingBox &bbox,string src_proj4_coord_system,string dst_proj4_coord_system,double sparseRatio,bool no_hw_context,bool no_atlas){ //vector<osg::KdTree*> trees; vpb::GeospatialExtents geo(bounds.bbox.xMin(), bounds.bbox.yMin(), bounds.bbox.xMax(),bounds.bbox.yMax(),false); int numlod=datalist_lod.size(); if(useVirtualTex) useReimage=false; osg::ref_ptr<vpb::MyDataSet> m=new vpb::MyDataSet(calib,basePath,useTextureArray,useReimage,useVirtualTex); if(useVirtualTex) m->_atlas=createVTAtlas( m->viewProj, m->totalX, m->totalY,POTAtlasSize, m->mosaic_cells, false); m->_cachedDirs=cachedDirs; m->_no_hw_context=no_hw_context; m->_zrange=osg::Vec4(bbox.zMin(),bbox.zMax(),bbox.zMin(),bbox.zMax()); m->setNumReadThreadsToCoresRatio(1.5); m->setNumWriteThreadsToCoresRatio(1.5); m->setDestinationCoordinateSystem(dst_proj4_coord_system); m->setSourceCoordinateSystemProj4(src_proj4_coord_system); m->sparseRatio=sparseRatio; // m->setCompressionMethod(vpb::BuildOptions::NVTT); //m->setCompressionMethod(vpb::BuildOptions::GL_DRIVER); //vpb::ImageOptions *imageOptions = new vpb::ImageOptions(); //imageOptions->setTextureType(vpb::ImageOptions::RGBA); //m->setLayerImageOptions(0,imageOptions); // m->setMaximumVisibleDistanceOfTopLevel(1e11); if(useVirtualTex) m->setRadiusToMaxVisibleDistanceRatio(7); else m->setRadiusToMaxVisibleDistanceRatio(7); m->setDestinationName("mesh/real.ive"); m->setLogFileName("tmp.log"); osgDB::Registry::instance()->setBuildKdTreesHint(osgDB::ReaderWriter::Options::BUILD_KDTREES); for(int lod=0/*datalist_lod.size()-1*/; lod < (int)datalist_lod.size(); lod++){ for(int i=0; i<(int)datalist_lod[lod].size(); i++){ if(!osgDB::fileExists(datalist_lod[lod][i])) continue; std::string mf=datalist_lod[lod][i]; int npos=mf.find("/"); std::string bbox_file; TexturedSource *sourceModel; // if(!useVirtualTex && !useReimage){ bbox_file=osgDB::getFilePath(mf)+"/bbox-"+osgDB::getSimpleFileName(mf).substr(0,osgDB::getSimpleFileName(mf).size()-9)+".ply.txt"; sourceModel =new TexturedSource(vpb::Source::MODEL,mf,bbox_file,!useVirtualTex && !useReimage,useVirtualTex || useReimage); // }else{ // sourceModel=new TexturedSource(vpb::Source::MODEL,mf); // } sourceModel->setMaxLevel(lod); sourceModel->setMinLevel(lod); sourceModel->setCoordinateSystem(new osg::CoordinateSystemNode("WKT","")); sourceModel->ids=NULL; osg::Node* model;/* ply::VertexDataMosaic vertexData; // if(!m->_useReImage && !m->_useVirtualTex) // { model= vertexData.readPlyFile(sourceModel->getFileName().c_str()); // cout <<vertexData._vertices->size() <<" "<<vertexData._triangles->size()<< " "<<vertexData._texCoord[0]->size()<<" "<<vertexData._texIds->size()<<endl; sourceModel->texAndAux->resize(vertexData._vertices->size()); for(int k=0; k<(int)vertexData._triangles->size()-2; k+=3){ for(int l=0; l <3; l++) sourceModel->texAndAux->at(vertexData._triangles->at(k+(2-l)))=osg::Vec4(vertexData._texCoord[0]->at(k+l)[0],vertexData._texCoord[0]->at(k+l)[1], vertexData._texIds->at(k/3)[0],vertexData._texIds->at(k/3)[1]); } //toVert(model,vertexData._texCoord,vertexData._texIds,sourceModel->tex,sourceModel->ids); //}else*/ model = osgDB::readNodeFile(sourceModel->getFileName()); // cout << model << " "<< sourceModel->getFileName()<<endl; if(lod == 0){ osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN); model->accept(cbbv); osg::BoundingBox totalbb = cbbv.getBoundingBox(); FILE *zrangefp=fopen("mesh/zrange.txt","w"); if(!zrangefp ){ fprintf(stderr,"Cannot open mesh/zrange.txt\n"); exit(-1); } fprintf(zrangefp,"%f %f\n",totalbb.zMin(),totalbb.zMax()); fclose(zrangefp); } //std::cerr << "aaa " << sourceModel->tex->at(0)->size() << " " << sourceModel->ids->size() <<endl; osg::ref_ptr<osg::KdTreeBuilder> _kdTreeBuilder = osgDB::Registry::instance()->getKdTreeBuilder()->clone(); model->accept(*_kdTreeBuilder); if (model) { vpb::SourceData* data = new vpb::SourceData(sourceModel); data->_model = model; data->_extents.expandBy(model->getBound()); // cout << model->getBound()._radius << " "<< model->getBound().center()<<endl; sourceModel->setSourceData(data); osg::Geode *geode= dynamic_cast<osg::Geode*>(model); if(geode && geode->getNumDrawables()){ osg::Drawable *drawable = geode->getDrawable(0); osg::Geometry *geom = dynamic_cast< osg::Geometry*>(drawable); sourceModel->colors=(osg::Vec4Array*)geom->getColorArray(); sourceModel->_kdTree = dynamic_cast<osg::KdTree*>(drawable->getShape()); // trees.push_back(sourceModel->_kdTree); }else{ osg::notify(osg::INFO) << "No drawbables \n"; } } m->addSource(sourceModel); } } m->createNewDestinationGraph(geo,256,128,numlod); m->_run(); // for(int i=0; i<trees.size(); i++) // delete trees[i]; }
void SimpleOceanLayer::modifyTileBoundingBox(const TileKey& key, osg::BoundingBox& box) const { // Force the max Z to be at least sea level, to satisfy the culling pass box.zMax() = std::max(box.zMax(), 0.0f); }