Hi all,

> > Maybe OSG should integrate
> >
> > http://www.mesa3d.org/brianp/TR.html

In my personal SDL-based viewer I've implemented a simple function that
takes arbitrary-size snapshots. With some tweaks to remove dependency on the
host class you should be able to use it in your application:

bool osgSDL::Viewer::exportSnapshot(const std::string &filename, int width,
int height, bool savetiles)
{
 if (viewports_.empty())
  return false;

 Viewport* vp = viewports_.front().get();
 osgUtil::SceneView* sv = vp->getSceneView();
 if (!sv)
  return false;

 double left, right, bottom, top, zNear, zFar;
 sv->getProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar);

 double ar = width / static_cast<double>(height);
 double target_frustum_h = top - bottom;
 double target_frustum_w = ar * target_frustum_h;
 double target_left = -target_frustum_w * 0.5;
 double target_right = target_frustum_w * 0.5;
 double target_bottom = -target_frustum_h * 0.5;
 double target_top = target_frustum_h * 0.5;

 int vpwidth = vp->getWidth() * getWidth();
 int vpheight = vp->getHeight() * getHeight();

 double newbottom = target_bottom;
 double newtop = newbottom + (target_top - target_bottom) * vpheight /
height;
 double newfrustum_h = newtop - newbottom;
 int t = 0;
 int s = 0;

 typedef std::vector<osg::ref_ptr<osg::Image> > Image_list;
 Image_list images;

 while (newbottom < target_top)
 {
  double frame_height = vpheight;

  if (newtop > target_top)
   frame_height = height % vpheight;

  double newleft = target_left;
  double newright = newleft + (target_right - target_left) * vpwidth /
width;
  double newfrustum_w = newright - newleft;
  s = 0;

  while (newleft < target_right)
  {
   double frame_width = vpwidth;

   if (newright > target_right)
    frame_width = width % vpwidth;

   sv->setProjectionMatrixAsFrustum(newleft, newright, newbottom, newtop,
zNear, zFar);
   cull(sv);
   draw(sv);

   std::ostringstream oss;
   oss << osgDB::getNameLessExtension(filename) << "_" << s << "_" << t <<
"." << osgDB::getFileExtension(filename);
   osg::ref_ptr<osg::Image> img = new osg::Image;
   images.push_back(img);
   img->readPixels(0, 0, frame_width, frame_height, GL_RGBA,
GL_UNSIGNED_BYTE);
   if (savetiles)
   {
    if (!osgDB::writeImageFile(*img.get(), oss.str()))
    {
     std::cerr << "Error writing " << oss.str() << "\n";
     return false;
    }
   }

   newleft += newfrustum_w;
   newright += newfrustum_w;
   ++s;
  }

  newbottom += newfrustum_h;
  newtop += newfrustum_h;
  ++t;
 }

 osg::ref_ptr<osg::Image> mosaic = new osg::Image;
 mosaic->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
 for (int i=0; i<t; ++i)
 {
  int yo = vpheight * i;
  for (int j=0; j<s; ++j)
  {
   int xo = vpwidth * j;
   mosaic->copySubImage(xo, yo, 0, images.at(j+i*s).get());
  }
 }

 if (!osgDB::writeImageFile(*mosaic.get(), filename))
 {
  std::cerr << "Error writing mosaic " << filename << "\n";
  return false;
 }

 return true;
}

Cheers,
Marco

_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/

Reply via email to