Hi,
    I am using Openscenegraph in VRJuggler.I want to update the scene.Since 
there wont be any things like viewer.run() or viewer.updateTraversal I dont 
know how to update my scene.There's update() method but the update() method 
uses a predefined nodecallback to update the scene and its defined private.I am 
attaching the header file that contains the nodecallbackmethods.

Thank you!

Cheers,
Tim

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=17097#17097



/*************** <auto-copyright.pl BEGIN do not edit this line> **************
 *
 * VR Juggler is (C) Copyright 1998-2007 by Iowa State University
 *
 * Original Authors:
 *   Allen Bierbaum, Christopher Just,
 *   Patrick Hartling, Kevin Meinert,
 *   Carolina Cruz-Neira, Albert Baker
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 *************** <auto-copyright.pl END do not edit this line> ***************/

#ifndef _VRJ_OSG_APP_H_
#define _VRJ_OSG_APP_H_

#include <vrj/vrjConfig.h>

#include <vpr/Sync/Mutex.h>
#include <vpr/Sync/Guard.h>

#include <vrj/Draw/OGL/GlApp.h>
#include <vrj/Draw/OGL/GlContextData.h>
#include <vrj/Draw/OGL/GlWindow.h>

#include <vrj/Display/CameraProjection.h>

#include <vrj/Kernel/Kernel.h>
#include <vrj/Kernel/User.h>

#include <osg/Version>
#include <osg/Vec3>
#include <osg/Matrix>
#include <osg/Transform>
#include <osg/Group>

#include <osgUtil/SceneView>
#include <osgUtil/UpdateVisitor>


namespace vrj
{

/** \class OsgApp OsgApp.h vrj/Draw/OSG/OsgApp.h
 *
 * Encapsulates an Open Scene Graph (OSG) application.  This defines the base
 * class from which OSG-based application classes should be derived.  It makes
 * use of the OpenGL Draw Manager.
 *
 * @note This class makes use of gadget::PositionInterface internally and
 *       requires that a proxy or proxy alias named "VJHead" is defined in
 *       the VR Juggler configuration.
 *
 * @see vrj::GlApp
 */
class OsgApp : public GlApp
{
public:
   OsgApp(Kernel* kern = NULL)
      : GlApp(kern)
      , mFrameNumber(0)
   {
      // Tell osg::Referenced to use thread-safe reference counting. We do
      // this here for all applications and all configurations though it is
      // only strictly necessary when VR Juggler is configured to use
      // multi-threaded rendering.
      osg::Referenced::setThreadSafeReferenceCounting(true);
   }

   virtual ~OsgApp()
   {
      ;
   }

   /**
    * Initializes the scene.
    * Called by init() to initialize the scene.
    */
   virtual void initScene() = 0;

   /**
    * Gets the root of the scene to render.
    * Called each frame to get the current scene to render.
    */
   virtual osg::Group* getScene() = 0;

   /**
    * Returns the options to be passed to osgUtil::SceneView::setDefaults()
    * for each scene view that is configured. This is called by the default
    * implementation of vrj::OsgApp::configSceneView(). See
    * osgUtil::SceneView::Options for the available settings.
    *
    * @see configSceneView()
    *
    * @note The signatue of this method changed after VR Juggler 2.2.0 was
    *       released. Instead of returning osgUtil::SceneView::Options, it
    *       now returns unsigned int.
    *
    * @since 2.1.26
    */
   virtual unsigned int getSceneViewDefaults()
   {
      return osgUtil::SceneView::STANDARD_SETTINGS;
   }

   /**
    * Configures newly created scene viewers.
    * This is called immediately after a new scene viewer is created for a
    * context.  This is the place to configure application background colors
    * and other viewer-specific information.  Below are some suggestions on
    * how to configure an osgUtil::SceneView instance with lighting.
    *
    * For an application configure with a sky light:
    *
    * \code
    * unsigned int MyApp::getSceneViewDefaults()
    * {
    *    return osgUtil::SceneView::SKY_LIGHT;
    * }
    * \endcode
    *
    * For an application configured with a headlight:
    *
    * \code
    * unsigned int MyApp::getSceneViewDefaults()
    * {
    *    return osgUtil::SceneView::HEADLIGHT;
    * }
    * \endcode
    *
    * For an application configure with a user-defined light, there are
    * several steps.
    *
    * \code
    * // First, declare two member variables in your subclass of vrj::OsgApp
    * such as the following:
    * osg::ref_ptr<osg::Light> mLight0;
    * osg::ref_ptr<osg::LightSource> mLightSource0;
    *
    * // Then, in init() do something such as the following:
    * void MyApp::init()
    * {
    *    vrj::OsgApp::init();
    *
    *    mLight0 = new osg::Light();
    *    mLight0->setLightNum(0);
    *    mLight0->setAmbient(osg::Vec4f(0.36862f, 0.36842f, 0.36842f, 1.0f));
    *    mLight0->setDiffuse(osg::Vec4f(0.88627f, 0.88500f, 0.88500f, 1.0f));
    *    mLight0->setSpecular(osg::Vec4f(0.49019f, 0.48872f, 0.48872f, 1.0f));
    *    mLight0->setPosition(osg::Vec4f(10000.0f, 10000.0f, 10000.0f, 0.0f));
    *    mLight0->setDirection(osg::Vec3f(-1.0f, -1.0f, -1.0f));
    *
    *    mLightSource0 = new osg::LightSource();
    *    mLightSource0->setLight(mLight0.get());
    *    mLightSource0->setLocalStateSetModes(osg::StateAttribute::ON);
    *
    *    // Now that we know we have a root node add the default light to the
    *    // scene.
    *    this->getScene()->addChild( mLightSource0.get() );
    * }
    *
    * // Next, override vrj::OsgApp::getSceneViewDefaults() to change the
    * // option passed to osgUtil::SceneView::setDefaults().
    * unsigned int MyApp::getSceneViewDefaults()
    * {
    *    return osgUtil::SceneView::NO_SCENEVIEW_LIGHT;
    * }
    *
    * // Finally, set up the osgUtil::SceneView instance to use this light.
    * void MyApp::configSceneView(osgUtil::SceneView* newSceneViewer)
    * {
    *    vrj::OsgApp::configSceneView(newSceneViewer);
    *
    *    // add lights and turn on lighting
    *    newSceneViewer->getGlobalStateSet()->setAssociatedModes(
    *       mLight0.get(), osg::StateAttribute::ON
    *    );
    *    newSceneViewer->getGlobalStateSet()->setMode(GL_LIGHTING,
    *                                                 osg::StateAttribute::ON);
    * }
    * \endcode
    *
    * @post \p newSceneViewer is initialized.
    *
    * @see getSceneViewDefaults()
    */
   virtual void configSceneView(osgUtil::SceneView* newSceneViewer)
   {
      newSceneViewer->setDefaults(getSceneViewDefaults());

      // Set the timing information in the scene view. This has to be done
      // only once per osgUtil::SceneView instance and should be done before
      // calling osgUtil::SceneView::init().
      newSceneViewer->setFrameStamp(mFrameStamp.get());

      newSceneViewer->init();
      newSceneViewer->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f, 0.0f));

      // Needed for stereo to work.
      newSceneViewer->setDrawBufferValue(GL_NONE);
   }

   /**
    * Function called after preFrame() and application-specific data
    * synchronization (in a cluster configuration) but before the start of a
    * new frame.
    *
    * If this method is overridden, it must be called as the last thing done
    * by the overriding version.  This calls update(), which is used to update
    * this application object's scene graph.
    *
    * @note Subclasses overriding this method \em must call this method
    *       implementation as the last step.
    *
    * @since 2.1.9
    */
   virtual void latePreFrame()
   {
      update();
   }

   /**
    * Function to set up and render the scene using OSG.  Override this
    * method with great care.  All the logic to handle multi-pipe rendering
    * and other VR Juggler features happens here.
    *
    * @pre OpenGL state has correct transformation and buffer selected.
    * @post The current scene has been drawn.
    */
   virtual void draw();

   /**
    * Application initialization function.
    * Execute any initialization needed before the graphics API is started.
    * If this method is overridden, it must be called by the overriding
    * version.  This calls initScene(), which is used to set up this
    * application object's scene graph.
    *
    * @note Derived classes MUST call base class version of this method.
    */
   virtual void init()
   {
      mUpdateVisitor = new osgUtil::UpdateVisitor();
      mFrameStamp    = new osg::FrameStamp();
      mUpdateVisitor->setFrameStamp(mFrameStamp.get());

      GlApp::init();

      //Create the scene
      this->initScene();
   }

   /**
    * Function that is called immediately after a new context is created.
    * Use this function to create context-specific data structures such as
    * display lists and texture objects that are known to be required when
    * the context is created.
    *
    * @pre The OpenGL context has been set to the new context.
    * @post The application has completed context-specific initialization.
    */
   void contextInit();

   /**
    * Function that is called immediately before a context is closed.
    * Use the function to clean up any context-specific data structures.
    */
   virtual void contextClose()
   {
      ;
   }

   /**
    * Function that is called upon entry into the context before rendering.
    * This can be used to allocate context-specific data dynamically.
    *
    * @pre The OpenGL context has been set to the context for drawing.
    * @post The application object has executed any commands that need to be
    *       executed only once per context, per frame.
    *
    * @note This function can be used for things that need to happen
    *       every frame but only once per context.
    */
   virtual void contextPreDraw()
   {
      ;
   }

   /**
    * Function that is called once for each frame buffer of an OpenGL context.
    * This function is executed after contextInit() (if needed) but before
    * contextPreDraw().  It is called once per frame buffer (see note).
    *
    * @pre The OpenGL context has been set to the context for drawing.
    * @post The application object has executed any commands that need to be
    *        executed once per context, per buffer, per frame.
    *
    * @note This function is designed to be used when some task must be
    *       performed only once per frame buffer (i.e., once for the left
    *       buffer, once for the right buffer).  For example, the OpenGL clear
    *       color should be defined and glClear(GL_COLOR_BUFFER_BIT) should be
    *       called in this method.
    */
   virtual void bufferPreDraw()
   {
      ;
   }

   /**
    * Function that is called at the beginning of the drawing of each pipe.
    *
    * @pre The library is preparing to render all windows on a given pipe.
    * @post Any pre-pipe user calls have been done.
    *
    * @note Currently the OpenGL context is not set when this function is
    *       called.  This is a TEST function.  USE AT YOUR OWN RISK!!!
    */
   virtual void pipePreDraw()
   {
      ;
   }

protected:
   /**
    * Performs the update stage on the scene graph.  This function should be
    * called as the last thing that happens in latePreFrame(). If
    * latePreFrame() is not overridden, then this happens automatically.
    * Otherwise be sure to call vrj::OsgApp::latePreFrame() as the last thing
    * in application object's override of latePreFrame().
    *
    * @pre The library is preparing to switch from the serial preDraw stages
    *      to the parallel draw stages.
    * @post The scene graph update stage is complete and it is ready for cull
    *       and draw to be called in parallel.
    *
    * @note This function also takes care of time-based features in the scene
    *       graph.
    *
    * @since 2.1.9
    */
   void update()
   {
      ++mFrameNumber;

      // Update the frame stamp with information from this frame.
      mFrameStamp->setFrameNumber(mFrameNumber);

      const double head_time(
         mKernel->getUsers()[0]->getHeadPosProxy()->getTimeStamp().secd()
      );
      mFrameStamp->setReferenceTime(head_time);
#if OSG_VERSION_MAJOR == 1 && OSG_VERSION_MINOR > 2 || OSG_MAJOR_VERSION >= 2
      // This is available in OSG 1.9 and newer.
      mFrameStamp->setSimulationTime(head_time);
#endif
      
      // Set up the time and frame number so time-dependent things (animations,
      // particle system) function correctly.
      // XXX: This may not be necessary.
      mUpdateVisitor->setTraversalNumber(mFrameNumber);

      // Update the scene by traversing it with the the update visitor which
      // will call all node update callbacks and animations. This is
      // equivalent to calling osgUtil::SceneView::update() but does not
      // require access to the context-specific osgUtil::SceneView instance.
      getScene()->accept(*mUpdateVisitor);
      
      // NOTE: This comment was taken from osgUtil::SceneView::update():
      // Now force a recompute of the bounding volume while we are still in
      // the read/write app phase, this should prevent the need to recompute
      // the bounding volumes from within the cull traversal which may be
      // multi-threaded.
      getScene()->getBound();
   }

   vrj::GlContextData< osg::ref_ptr<osgUtil::SceneView> > sceneViewer;

private:
   osg::ref_ptr<osg::NodeVisitor> mUpdateVisitor;
   osg::ref_ptr<osg::FrameStamp> mFrameStamp;

   int mFrameNumber;
   vpr::Mutex mSceneViewLock;
};

inline void OsgApp::contextInit()
{
   const unsigned int unique_context_id =
      GlDrawManager::instance()->getCurrentContext();

   // --- Create new context specific scene viewer -- //
   osg::ref_ptr<osgUtil::SceneView> new_sv(new osgUtil::SceneView);
   this->configSceneView(new_sv.get());            // Configure the new viewer
   new_sv->getState()->setContextID(unique_context_id);
   // Add the tree to the scene viewer and set properties
   {
      vpr::Guard<vpr::Mutex> sv_guard(mSceneViewLock);
      new_sv->setSceneData(getScene());
   }

   (*sceneViewer) = new_sv;
}

inline void OsgApp::draw()
{
   glClear(GL_DEPTH_BUFFER_BIT);

   // Users have reported problems with OpenGL reporting stack underflow
   // problems when the texture attribute bit is pushed here, so we push all
   // attributes *except* GL_TEXTURE_BIT.
   glPushAttrib(GL_ALL_ATTRIB_BITS & ~GL_TEXTURE_BIT);
   glPushAttrib(GL_TRANSFORM_BIT);
   glPushAttrib(GL_VIEWPORT_BIT);

   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();

   glMatrixMode(GL_PROJECTION);
   glPushMatrix();

   osg::ref_ptr<osgUtil::SceneView> sv;
   sv = (*sceneViewer);    // Get context specific scene viewer
   vprASSERT(sv.get() != NULL);

   // The OpenGL Draw Manager that we are rendering for.
   //Get the view matrix and the frustrum form the draw manager
   GlDrawManager* gl_manager =
      dynamic_cast<GlDrawManager*>(this->getDrawManager());
   vprASSERT(gl_manager != NULL);
   GlUserData* user_data = gl_manager->currentUserData();

   // Set the up the viewport (since OSG clears it out)
   float vp_ox, vp_oy, vp_sx, vp_sy;   // The float vrj sizes of the view ports
   int w_ox, w_oy, w_width, w_height;  // Origin and size of the window
   user_data->getViewport()->getOriginAndSize(vp_ox, vp_oy, vp_sx, vp_sy);
   user_data->getGlWindow()->getOriginSize(w_ox, w_oy, w_width, w_height);

   // compute unsigned versions of the viewport info (for passing to glViewport)
   const unsigned int ll_x =
      static_cast<unsigned int>(vp_ox * static_cast<float>(w_width));
   const unsigned int ll_y =
      static_cast<unsigned int>(vp_oy * static_cast<float>(w_height));
   const unsigned int x_size =
      static_cast<unsigned int>(vp_sx * static_cast<float>(w_width));
   const unsigned int y_size =
      static_cast<unsigned int>(vp_sy * static_cast<float>(w_height));

   //sv->setCalcNearFar(false);
   sv->setComputeNearFarMode(osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR);
   sv->setViewport(ll_x, ll_y, x_size, y_size);

   //Get the frustrum
   Projection* project = user_data->getProjection();
   Frustum frustum = project->getFrustum();
   sv->setProjectionMatrixAsFrustum(frustum[Frustum::VJ_LEFT],
                                    frustum[Frustum::VJ_RIGHT],
                                    frustum[Frustum::VJ_BOTTOM],
                                    frustum[Frustum::VJ_TOP],
                                    frustum[Frustum::VJ_NEAR],
                                    frustum[Frustum::VJ_FAR]);

   // Copy the view matrix
   sv->setViewMatrix(osg::Matrix(project->getViewMatrix().mData));

   //Draw the scene
   // NOTE: It is not safe to call osgUtil::SceneView::update() here; it
   // should only be called by a single thread. The equivalent of calling
   // osgUtil::SceneView::update() is in vrj::OsgApp::update().
   sv->cull();
   sv->draw();

   glMatrixMode(GL_PROJECTION);
   glPopMatrix();

   glMatrixMode(GL_MODELVIEW);
   glPopMatrix();

   glPopAttrib();
   glPopAttrib();
   glPopAttrib();
}

}


#endif /* _VRJ_OSG_APP_H_ */
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to