Hi!

Since people keep saying that OSG is easy, I thought I'd ask here
before I go over to the OSG list.

I have modified the osgdistortion example so that it uses an
intermediate image instead of directly rendering to the texture. I did
this to simulate my problem with rendering to an image.
Here is the relevant part (front face in setDomeCorrection):

        osg::ref_ptr<osg::GraphicsContext::Traits> traits2 = new
osg::GraphicsContext::Traits;
        traits2->width = camera_width;
        traits2->height = camera_height;
        traits2->pbuffer = true;
        osg::ref_ptr<osg::GraphicsContext> gc2 =
osg::GraphicsContext::createGraphicsContext(traits2.get());
//      gc2->realize();
        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
        camera->setName("Front face camera");
        camera->setGraphicsContext(gc2.get());
        camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
        camera->setAllowEventFocus(false);
        // tell the camera to use OpenGL frame buffer object where supported.
        camera->setRenderTargetImplementation(renderTargetImplementation);

        // attach the texture and use it as the color buffer.
        osg::ref_ptr<osg::Image> image = new osg::Image;
        image->allocateImage(camera_width, camera_height, 1, GL_RGB,
GL_UNSIGNED_BYTE);
        camera->attach(osg::Camera::COLOR_BUFFER, image.get());

This works as expected. Note however, that I have not called realize()
on the gc. If I do, I get errors:

Warning: GraphicsWindow not realized, cannot do makeCurrent.
Error: In Texture::Extensions::setupGLExtensions(..) OpenGL version
test failed, requires valid graphics context.

Now, if I put the code into flightgear, I get the above errors if I
_don't_ call realize()!
That is, just the opposite behavior. But even if I call realize(), in
the post-draw callback my image only contains the background color.
Furthermore, if I try to call setDrawBuffer(GL_FRONT) or
setReadBuffer(GL_FRONT), I get:

before Font::Glyph::subload(): detected OpenGL error 'invalid enumerant
Warning: detected OpenGL error 'invalid enumerant' after RenderBin::draw(,)
(and lot more follow, I guess one per frame)

The only way I got it to work was to not call attach(), add a
FinalDrawCallback and use readPixels().

I guess this is suboptimal in terms of performance and I am puzzled anyway.
Any ideas what could cause such behavior?
Also, even though I have multiple cameras and multiple graphics
contexts, I could not see any multi-threading no matter how I set
/sim/rendering/multithreading-mode (it does show up on the stats
screen properly, though).

I have attached the patches and the config file I use. Run as:
$ mkfifo /tmp/fg-snapshot
$ mplayer -demuxer rawvideo -rawvideo format=rgb24:w=480:h=300 -vf
flip /tmp/fg-snapshot
(in another shell)
$ fgfs --config=camera.xml

Then, set /sim/video=1 to start streaming. Ideally, you should see
your fg view (minus gui elements) playing in the mplayer window.
You can select the attach vs. readPixels implementation by changing
the ATTACH define in the source.

-- 
Thanks,
Csaba/Jester
Index: osgdistortion.cpp
===================================================================
--- osgdistortion.cpp	(revision 9007)
+++ osgdistortion.cpp	(working copy)
@@ -444,6 +444,30 @@
     return geometry;
 }
 
+struct MyCameraPostDrawCallback : public osg::Camera::DrawCallback
+{
+    MyCameraPostDrawCallback(Image* image) : _f(0), _image(image) {};
+    ~MyCameraPostDrawCallback()
+    {
+	if (_f)
+	{
+	    fclose(_f);
+	    _f = 0;
+	}
+    }
+    
+    virtual void operator () (const osg::Camera& camera) const
+    {
+	if (!_f) _f = fopen("/tmp/fg-snapshot", "wb");
+	fwrite(_image->data(), _image->getTotalSizeInBytes(), 1, _f);
+	fflush(_f);
+    }
+
+    private:
+	mutable FILE* _f;
+	ref_ptr<Image> _image;
+};
+
 void setDomeCorrection(osgViewer::Viewer& viewer, osg::ArgumentParser& arguments)
 {
  
@@ -501,18 +525,26 @@
 
     // front face
     {
-        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
+        osg::ref_ptr<osg::GraphicsContext::Traits> traits2 = new osg::GraphicsContext::Traits;
+        traits2->width = camera_width;
+        traits2->height = camera_height;
+        traits2->pbuffer = true;
+        osg::ref_ptr<osg::GraphicsContext> gc2 = osg::GraphicsContext::createGraphicsContext(traits2.get());
+//      gc2->realize();
+        osg::ref_ptr<osg::Camera> camera = new osg::Camera;	
         camera->setName("Front face camera");
-        camera->setGraphicsContext(gc.get());
+        camera->setGraphicsContext(gc2.get());
         camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height));
-        camera->setDrawBuffer(buffer);
-        camera->setReadBuffer(buffer);
         camera->setAllowEventFocus(false);
         // tell the camera to use OpenGL frame buffer object where supported.
         camera->setRenderTargetImplementation(renderTargetImplementation);
 
         // attach the texture and use it as the color buffer.
-        camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_Y);
+        osg::ref_ptr<osg::Image> image = new osg::Image;
+        image->allocateImage(camera_width, camera_height, 1, GL_RGB, GL_UNSIGNED_BYTE);
+        camera->attach(osg::Camera::COLOR_BUFFER, image.get());
+        texture->setImage(osg::TextureCubeMap::POSITIVE_Y, image.get());
+        camera->setPostDrawCallback(new MyCameraPostDrawCallback(image.get()));
 
         viewer.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd());
     }
<PropertyList>
    <sim>
	<rendering>
	    <camera-group>
		<gui>
		    <window>
			<name>Main</name>
			<width>1800</width>
			<height>1125</height>
		    </window>
		</gui>
		<camera>
		    <window>
			<name>Main</name>
		    </window>
		</camera>
		<camera>
		    <image>
			<width>480</width>
			<height>300</height>
		    </image>
		</camera>
	    </camera-group>
	</rendering>
    </sim>
</PropertyList>
Index: CameraGroup.cxx
===================================================================
RCS file: /var/cvs/FlightGear-0.9/source/src/Main/CameraGroup.cxx,v
retrieving revision 1.1
diff -u -r1.1 CameraGroup.cxx
--- CameraGroup.cxx	1 Aug 2008 15:57:33 -0000	1.1
+++ CameraGroup.cxx	10 Oct 2008 15:32:01 -0000
@@ -22,10 +22,12 @@
 #include "WindowBuilder.hxx"
 #include "WindowSystemAdapter.hxx"
 #include <simgear/props/props.hxx>
+#include "fg_props.hxx"
 
 #include <algorithm>
 #include <cstring>
 #include <string>
+#include <iostream>
 
 #include <osg/Camera>
 #include <osg/GraphicsContext>
@@ -124,26 +126,91 @@
 
 namespace flightgear
 {
+
+#define ATTACH 1
+struct MyCameraPostDrawCallback : public osg::Camera::DrawCallback
+{
+    MyCameraPostDrawCallback(Image* image) : _f(0), _image(image) {};
+    ~MyCameraPostDrawCallback()
+    {
+        if (_f)
+        {
+            fclose(_f);
+            _f = 0;
+        }
+    }
+    
+    virtual void operator () (const osg::Camera& camera) const
+    {
+        if (fgGetBool("/sim/video"))
+        {
+            if (!_f) _f = fopen("/tmp/fg-snapshot", "wb");
+#if !ATTACH	    
+            _image->readPixels(0, 0, _image->s(), _image->t(), GL_RGB, GL_UNSIGNED_BYTE);
+#endif	    
+            fwrite(_image->data(), _image->getTotalSizeInBytes(), 1, _f);
+            fflush(_f);
+        }
+//      std::cerr << "RTT CAMERA DRAWN, children = " << camera.getNumChildren() << std::endl;
+    }
+
+    private:
+        mutable FILE* _f;
+        ref_ptr<Image> _image;
+};
+
 CameraInfo* CameraGroup::buildCamera(const SGPropertyNode* cameraNode)
 {
     WindowBuilder *wBuild = WindowBuilder::getWindowBuilder();
     const SGPropertyNode* windowNode = cameraNode->getNode("window");
+    const SGPropertyNode* imageNode = cameraNode->getNode("image");
     GraphicsWindow* window = 0;
+    ref_ptr<Image> image;
     static int cameraNum = 0;
-    int cameraFlags = DO_INTERSECTION_TEST;
     if (windowNode) {
         // New style window declaration / definition
         window = wBuild->buildWindow(windowNode);
+    } else if (imageNode) {
+        int width = imageNode->getIntValue("width", 480);
+        int height = imageNode->getIntValue("height", 300);
+        image = new Image();
+        image->allocateImage(width, height, 1, GL_RGB, GL_UNSIGNED_BYTE);
+        std::cerr << "video image r = " << image->r() << ", s = " << image->s() << ", t = " << image->t() << ", size = " << image->getTotalSizeInBytes() << std::endl;	
     } else {
         // Old style: suck window params out of camera block
         window = wBuild->buildWindow(cameraNode);
     }
-    if (!window) {
+    if (!window && !image) {
         return 0;
     }
     Camera* camera = new Camera;
     camera->setAllowEventFocus(false);
-    camera->setGraphicsContext(window->gc.get());
+    int cameraFlags = 0;
+    if (!image)
+    {
+        camera->setGraphicsContext(window->gc.get());
+        cameraFlags |= DO_INTERSECTION_TEST;
+    } else {
+        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
+        traits->width = image->s();
+        traits->height = image->t();
+        traits->pbuffer = true;
+        ref_ptr<GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
+        gc->realize();
+        camera->setGraphicsContext(gc.get());
+        camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
+        camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+        camera->setClearColor(osg::Vec4(0.0f, 0.0f, 1.0f , 0.0f));
+//      camera->setDrawBuffer(GL_FRONT);
+//      camera->setReadBuffer(GL_FRONT);
+#if ATTACH	
+        camera->attach(osg::Camera::COLOR_BUFFER, image.get());
+        camera->setPostDrawCallback(new MyCameraPostDrawCallback(image.get()));
+#else	
+        camera->setFinalDrawCallback(new MyCameraPostDrawCallback(image.get()));
+#endif	
+        std::cerr << "VIDEO CAMERA SET UP" << std::endl;
+    }
     // If a viewport isn't set on the camera, then it's hard to dig it
     // out of the SceneView objects in the viewer, and the coordinates
     // of mouse events are somewhat bizzare.
@@ -151,6 +218,8 @@
     Viewport* viewport = 0;
     if (viewportNode) {
         viewport = buildViewport(viewportNode);
+    } else if (image) {
+        viewport = new Viewport(0, 0, image->s(), image->t());
     } else {
         const GraphicsContext::Traits *traits = window->gc->getTraits();
         viewport = new Viewport(0, 0, traits->width, traits->height);
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel

Reply via email to