From: Markus R. <rol...@us...> - 2007-04-09 17:33:56
|
Update of /cvsroot/simspark/simspark/spark/kerosin/renderserver In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv950 Modified Files: renderserver.cpp renderserver.h Log Message: - added support for OpenGL object picking. When enabled the RenderServer determines the closest object to the given OpenGL window coordinates. This allows for object selection with the mouse - added public methods EnablePicking(), DisablePicking() and GetPickedNode() Index: renderserver.h =================================================================== RCS file: /cvsroot/simspark/simspark/spark/kerosin/renderserver/renderserver.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** renderserver.h 15 Mar 2007 07:26:26 -0000 1.3 --- renderserver.h 9 Apr 2007 17:02:25 -0000 1.4 *************** *** 44,47 **** --- 44,48 ---- #include <oxygen/sceneserver/sceneserver.h> #include <kerosin/openglserver/glbase.h> + #include <kerosin/openglserver/openglwrapper.h> namespace oxygen *************** *** 56,59 **** --- 57,61 ---- { class OpenGLServer; + class RenderNode; class RenderServer : public zeitgeist::Leaf *************** *** 63,66 **** --- 65,71 ---- // public: + typedef std::map<GLuint, boost::weak_ptr<kerosin::RenderNode> > TGLNameMap; + + public: RenderServer(); ~RenderServer(); *************** *** 81,84 **** --- 86,98 ---- virtual void UpdateCached(); + /** If enabled the next render pass is used to pick an object */ + void EnablePicking(bool enable, const salt::Vector2f& pickAt, const double pickRange); + + /** Disables object picking for the next render pass */ + void DisablePicking(); + + /** Returns the last picked node */ + boost::weak_ptr<RenderNode> GetPickedNode() const; + protected: /** get the active scene node from the sceneServer */ *************** *** 100,103 **** --- 114,125 ---- void BindCamera(boost::shared_ptr<oxygen::Camera>& camera); + /** clears last intermediate picking state and prepares OpenGL + picking + */ + void PreparePicking(); + + /** processes the collected picking information */ + void ProcessPicks(); + // // Members *************** *** 110,130 **** CachedPath<oxygen::SceneServer> mSceneServer; RGBA mAmbientColor; - }; - - DECLARE_CLASS(RenderServer); - - } //namespace kerosin - - #endif // KEROSIN_RENDERSERVER_H --- 132,162 ---- CachedPath<oxygen::SceneServer> mSceneServer; + /** the OpenGL ambient clear color */ RGBA mAmbientColor; + /** OpenGL name to RenderNode map for object picking */ + TGLNameMap mNameMap; + /** counter to assign OpenGL names to RenderNodes while picking */ + GLuint mNextName; + /** true, iff picking is enabled */ + bool mEnablePicking; + /** the picking position in OpenGL window coordinates */ + salt::Vector2f mPickAt; + /** the pick radius around mPickAt */ + double mPickRange; + /** the picked result node */ + boost::weak_ptr<RenderNode> mPickedNode; + }; + DECLARE_CLASS(RenderServer); + } //namespace kerosin + #endif // KEROSIN_RENDERSERVER_H Index: renderserver.cpp =================================================================== RCS file: /cvsroot/simspark/simspark/spark/kerosin/renderserver/renderserver.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** renderserver.cpp 15 Mar 2007 07:26:26 -0000 1.3 --- renderserver.cpp 9 Apr 2007 17:02:25 -0000 1.4 *************** *** 36,42 **** --- 36,49 ---- using namespace zeitgeist; + /** OpenGL picking result buffer */ + static GLuint gSelectBuffer[4096]; + RenderServer::RenderServer() : Leaf() { mAmbientColor = RGBA(0.0,0.0,0.0,0.0); + mEnablePicking = false; + mPickAt = Vector2f(0.0,0.0); + mPickRange = 10.0; + mNextName = 1; } *************** *** 86,91 **** --- 93,109 ---- void + RenderServer::PreparePicking() + { + mNameMap.clear(); + mNextName = 1; + glSelectBuffer(sizeof(gSelectBuffer), gSelectBuffer); + mPickedNode.reset(); + } + + void RenderServer::Render() { + PreparePicking(); + if (! GetActiveScene()) { *************** *** 153,156 **** --- 171,235 ---- // reset GL lights glDisable(GL_LIGHTING); + + if (mEnablePicking) + { + ProcessPicks(); + } + } + + void + RenderServer::ProcessPicks() + { + // restoring the original projection matrix + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glFlush(); + + // returning to normal rendering mode + int hits = glRenderMode(GL_RENDER); + + // if there are hits process them + GLuint numberOfNames = 0; + GLuint minZ = 0xffffffff; + GLuint *ptrNames = 0; + + GLuint* ptr = gSelectBuffer; + + for (int i = 0; i < hits; i++) + { + // read number of stored names in the current record + GLuint names = (*ptr); + ptr++; + + if ((*ptr) < minZ) + { + numberOfNames = names; + minZ = *ptr; + ptrNames = ptr+2; + } + + ptr += names+2; + } + + mPickedNode.reset(); + for (;;) + { + if (ptrNames == 0) + { + break; + } + + TGLNameMap::const_iterator iter = mNameMap.find(*ptrNames); + if (iter == mNameMap.end()) + { + break; + } + + mPickedNode = (*iter).second; + break; + } + + mNameMap.clear(); } *************** *** 163,170 **** --- 242,264 ---- { glPushMatrix(); + + if (mEnablePicking) + { + // assign an OpenGL name to the RenderNode + GLuint name = (mNextName++); + mNameMap[name] = renderNode; + glPushName(name); + } + glMultMatrixf(node->GetWorldTransform().m); renderNode->RenderInternal(); + if (mEnablePicking) + { + // pop name from OpenGL name stack + glPopName(); + } + glPopMatrix(); } *************** *** 199,211 **** glDepthRange(0, 1); ! // setup the projection matrix ! glMatrixMode(GL_PROJECTION); ! glLoadIdentity(); ! glMultMatrixf(camera->GetProjectionTransform().m); ! // initialize the modelview stack ! glMatrixMode(GL_MODELVIEW); ! glLoadIdentity(); ! glMultMatrixf(camera->GetViewTransform().m); } --- 293,325 ---- glDepthRange(0, 1); ! if (mEnablePicking) ! { ! glRenderMode(GL_SELECT); ! GLint viewport[4]; ! glGetIntegerv(GL_VIEWPORT, viewport); ! ! glMatrixMode(GL_PROJECTION); ! glPushMatrix(); ! glLoadIdentity(); ! ! gluPickMatrix(mPickAt[0],viewport[3]-mPickAt[1],mPickRange,mPickRange,viewport); ! ! glMultMatrixf(camera->GetProjectionTransform().m); ! glMatrixMode(GL_MODELVIEW); ! ! glInitNames(); ! } else ! { ! // setup the projection matrix ! glMatrixMode(GL_PROJECTION); ! glLoadIdentity(); ! glMultMatrixf(camera->GetProjectionTransform().m); ! ! // initialize the modelview stack ! glMatrixMode(GL_MODELVIEW); ! glLoadIdentity(); ! glMultMatrixf(camera->GetViewTransform().m); ! } } *************** *** 219,220 **** --- 333,351 ---- mActiveScene.reset(); } + + void RenderServer::DisablePicking() + { + mEnablePicking = false; + } + + void RenderServer::EnablePicking(bool enable, const Vector2f& pickAt, const double pickRange) + { + mEnablePicking = enable; + mPickAt = pickAt; + mPickRange = pickRange; + } + + weak_ptr<RenderNode> RenderServer::GetPickedNode() const + { + return mPickedNode; + } |