Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2011, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #ifndef OpenGLContext_INCLUDE_ONCE 00033 #define OpenGLContext_INCLUDE_ONCE 00034 00035 #include <vlCore/Object.hpp> 00036 #include <vlGraphics/UIEventListener.hpp> 00037 #include <vlGraphics/FramebufferObject.hpp> // Framebuffer and FramebufferObject 00038 #include <vlGraphics/RenderState.hpp> 00039 #include <vlGraphics/NaryQuickMap.hpp> 00040 #include <vector> 00041 #include <set> 00042 00043 namespace vl 00044 { 00045 class EnableSet; 00046 class RenderStateSet; 00047 class UniformSet; 00048 class IVertexAttribSet; 00049 class ArrayAbstract; 00050 00051 //----------------------------------------------------------------------------- 00052 // OpenGLContextFormat 00053 //----------------------------------------------------------------------------- 00055 class OpenGLContextFormat 00056 { 00057 public: 00058 OpenGLContextFormat(): 00059 mRGBABits(ivec4(8,8,8,8)), 00060 mAccumRGBABits(ivec4(0,0,0,0)), 00061 mHasDoubleBuffer(true), 00062 mZBufferBits(24), 00063 mStencilBufferBits(8), 00064 mHasMultisample(false), 00065 mMultisampleSamples(16), 00066 mStereo(false), 00067 mFullscreen(false), 00068 mVSync(false), 00069 mContextClientVersion(1) {} 00070 00071 void setRGBABits(int r, int g, int b, int a) { mRGBABits = ivec4(r,g,b,a); } 00072 void setAccumRGBABits(int r, int g, int b, int a) { mAccumRGBABits = ivec4(r,g,b,a); } 00073 void setDoubleBuffer(bool double_buffer_on) { mHasDoubleBuffer = double_buffer_on; } 00074 void setDepthBufferBits(int bits) { mZBufferBits = bits; } 00075 void setStencilBufferBits(int bits) { mStencilBufferBits = bits; } 00076 void setMultisample(bool multisample_on) { mHasMultisample = multisample_on; } 00077 void setMultisampleSamples(int samples) { mMultisampleSamples = samples; } 00078 void setStereo(bool stereo_on) { mStereo = stereo_on; } 00079 void setFullscreen(bool fullscreent) { mFullscreen = fullscreent; } 00080 void setVSync(bool vsync_on) { mVSync = vsync_on; } 00082 void setContextClientVersion(int version) { mContextClientVersion = version; } 00083 00084 const ivec4& rgbaBits() const { return mRGBABits; } 00085 const ivec4& accumRGBABits() const { return mAccumRGBABits; } 00086 bool doubleBuffer() const { return mHasDoubleBuffer; } 00087 int depthBufferBits() const { return mZBufferBits; } 00088 int stencilBufferBits() const { return mStencilBufferBits; } 00089 bool multisample() const { return mHasMultisample; } 00090 int multisampleSamples() const { return mMultisampleSamples; } 00091 bool stereo() const { return mStereo; } 00092 bool fullscreen() const { return mFullscreen; } 00093 bool vSync() const { return mVSync; } 00095 int contextClientVersion() const { return mContextClientVersion; } 00096 00098 int bitsPerPixel() const { return rgbaBits().r() + rgbaBits().g() + rgbaBits().b() + rgbaBits().a(); } 00099 00100 protected: 00101 ivec4 mRGBABits; 00102 ivec4 mAccumRGBABits; 00103 bool mHasDoubleBuffer; 00104 int mZBufferBits; 00105 int mStencilBufferBits; 00106 bool mHasMultisample; 00107 int mMultisampleSamples; 00108 bool mStereo; 00109 bool mFullscreen; 00110 bool mVSync; 00111 int mContextClientVersion; 00112 }; 00113 //----------------------------------------------------------------------------- 00114 // OpenGLContext 00115 //----------------------------------------------------------------------------- 00127 class VLGRAPHICS_EXPORT OpenGLContext: public Object 00128 { 00129 VL_INSTRUMENT_ABSTRACT_CLASS(vl::OpenGLContext, Object) 00130 friend class VertexAttrib; 00131 friend class Color; 00132 friend class SecondaryColor; 00133 friend class Normal; 00134 00135 public: 00137 OpenGLContext(int w=0, int h=0); 00138 00140 ~OpenGLContext(); 00141 00143 virtual void swapBuffers() = 0; 00144 00146 virtual void makeCurrent() = 0; 00147 00149 bool initGLContext(bool log=true); 00150 00152 void logOpenGLInfo(); 00153 00155 const std::string& extensions() const { return mExtensions; } 00156 00159 bool isExtensionSupported(const char* ext_name); 00160 00162 void* getProcAddress(const char* function_name); 00163 00167 Framebuffer* leftFramebuffer() { return mLeftFramebuffer.get(); } 00168 00172 const Framebuffer* leftFramebuffer() const { return mLeftFramebuffer.get(); } 00173 00177 Framebuffer* rightFramebuffer() { return mRightFramebuffer.get(); } 00178 00182 const Framebuffer* rightFramebuffer() const { return mRightFramebuffer.get(); } 00183 00186 Framebuffer* framebuffer() { return leftFramebuffer(); } 00187 00190 const Framebuffer* framebuffer() const { return leftFramebuffer(); } 00191 00193 ref<FramebufferObject> createFramebufferObject() { return createFramebufferObject(0,0); } 00194 00197 ref<FramebufferObject> createFramebufferObject(int width, int height, 00198 EReadDrawBuffer draw_buffer=RDB_COLOR_ATTACHMENT0, 00199 EReadDrawBuffer read_buffer=RDB_COLOR_ATTACHMENT0); 00200 00202 void destroyFramebufferObject(FramebufferObject* fbort); 00203 00205 void destroyAllFramebufferObjects(); 00206 00208 virtual void quitApplication() {} 00209 00211 virtual void update() = 0; 00212 00214 virtual void setWindowTitle(const String&) {} 00215 00217 virtual bool setFullscreen(bool) { mFullscreen = false; return false; } 00218 00220 virtual bool fullscreen() const { return mFullscreen; } 00221 00223 virtual void show() {} 00224 00226 virtual void hide() {} 00227 00229 virtual void setPosition(int /*x*/, int /*y*/) {} 00230 00232 virtual ivec2 position() const { return ivec2(); } 00233 00235 virtual void setSize(int /*w*/, int /*h*/) {} 00236 00238 int width() const { return framebuffer()->width(); } 00239 00241 int height() const { return framebuffer()->height(); } 00242 00244 virtual void setMouseVisible(bool) { mMouseVisible=false; } 00245 00247 virtual bool mouseVisible() const { return mMouseVisible; } 00248 00250 virtual void setMousePosition(int /*x*/, int /*y*/) {} 00251 00253 virtual void getFocus() {} 00254 00256 void setVSyncEnabled(bool enable); 00257 00259 bool vsyncEnabled() const; 00260 00262 virtual void setContinuousUpdate(bool continuous) { mContinuousUpdate = continuous; } 00263 00265 bool continuousUpdate() const { return mContinuousUpdate; } 00266 00270 void addEventListener(UIEventListener* el); 00271 00273 void removeEventListener(UIEventListener* el); 00274 00276 void eraseAllEventListeners(); 00277 00279 const std::vector< ref<UIEventListener> >& eventListeners() const { return mEventListeners; } 00280 00282 const UIEventListener* eventListener(int i) const { return mEventListeners[i].get(); } 00283 00285 UIEventListener* eventListener(int i) { return mEventListeners[i].get(); } 00286 00288 int eventListenerCount() const { return (int)mEventListeners.size(); } 00289 00291 const OpenGLContextFormat& openglContextInfo() const { return mGLContextInfo; } 00292 00294 void setOpenGLContextInfo(const OpenGLContextFormat& info) { mGLContextInfo = info; } 00295 00297 void ignoreNextMouseMoveEvent() { mIgnoreNextMouseMoveEvent = true; } 00298 00301 void dispatchResizeEvent(int w, int h) 00302 { 00303 makeCurrent(); 00304 leftFramebuffer()->setWidth(w); 00305 leftFramebuffer()->setHeight(h); 00306 rightFramebuffer()->setWidth(w); 00307 rightFramebuffer()->setHeight(h); 00308 00309 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00310 for( unsigned i=0; i<temp_clients.size(); ++i ) 00311 if ( temp_clients[i]->isEnabled() ) 00312 temp_clients[i]->resizeEvent( w, h ); 00313 } 00314 00316 void dispatchMouseMoveEvent(int x, int y) 00317 { 00318 makeCurrent(); 00319 if (mIgnoreNextMouseMoveEvent) 00320 mIgnoreNextMouseMoveEvent = false; 00321 else 00322 { 00323 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00324 for( unsigned i=0; i<temp_clients.size(); ++i ) 00325 if ( temp_clients[i]->isEnabled() ) 00326 temp_clients[i]->mouseMoveEvent(x, y); 00327 } 00328 } 00329 00331 void dispatchMouseUpEvent(EMouseButton button, int x, int y) 00332 { 00333 makeCurrent(); 00334 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00335 for( unsigned i=0; i<temp_clients.size(); ++i ) 00336 if ( temp_clients[i]->isEnabled() ) 00337 temp_clients[i]->mouseUpEvent(button, x, y); 00338 } 00339 00341 void dispatchMouseDownEvent(EMouseButton button, int x, int y) 00342 { 00343 makeCurrent(); 00344 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00345 for( unsigned i=0; i<temp_clients.size(); ++i ) 00346 if ( temp_clients[i]->isEnabled() ) 00347 temp_clients[i]->mouseDownEvent(button, x, y); 00348 } 00349 00351 void dispatchMouseWheelEvent(int n) 00352 { 00353 makeCurrent(); 00354 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00355 for( unsigned i=0; i<temp_clients.size(); ++i ) 00356 if ( temp_clients[i]->isEnabled() ) 00357 temp_clients[i]->mouseWheelEvent(n); 00358 } 00359 00361 void dispatchKeyPressEvent(unsigned short unicode_ch, EKey key) 00362 { 00363 makeCurrent(); 00364 keyPress(key); 00365 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00366 for( unsigned i=0; i<temp_clients.size(); ++i ) 00367 if ( temp_clients[i]->isEnabled() ) 00368 temp_clients[i]->keyPressEvent(unicode_ch, key); 00369 } 00370 00372 void dispatchKeyReleaseEvent(unsigned short unicode_ch, EKey key) 00373 { 00374 makeCurrent(); 00375 keyRelease(key); 00376 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00377 for( unsigned i=0; i<temp_clients.size(); ++i ) 00378 if ( temp_clients[i]->isEnabled() ) 00379 temp_clients[i]->keyReleaseEvent(unicode_ch, key); 00380 } 00381 00385 void dispatchDestroyEvent() 00386 { 00387 makeCurrent(); 00388 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00389 for( unsigned i=0; i<temp_clients.size(); ++i ) 00390 if ( temp_clients[i]->isEnabled() ) 00391 temp_clients[i]->destroyEvent(); 00392 destroyAllFramebufferObjects(); 00393 eraseAllEventListeners(); 00394 } 00395 00397 void dispatchRunEvent() 00398 { 00399 makeCurrent(); 00400 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00401 for( unsigned i=0; i<temp_clients.size(); ++i ) 00402 if ( temp_clients[i]->isEnabled() ) 00403 temp_clients[i]->updateEvent(); 00404 } 00405 00407 void dispatchVisibilityEvent(bool visible) 00408 { 00409 makeCurrent(); 00410 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00411 for( unsigned i=0; i<temp_clients.size(); ++i ) 00412 if ( temp_clients[i]->isEnabled() ) 00413 temp_clients[i]->visibilityEvent(visible); 00414 } 00415 00417 // - called as soon as the OpenGL context is available but before the first resize event 00418 // - when initEvent() is called all the supported OpenGL extensions are already available 00419 // - when initEvent() is called the window has already acquired its width and height 00420 // - only the enabled event listeners receive this message 00421 void dispatchInitEvent() 00422 { 00423 makeCurrent(); 00424 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00425 for( unsigned i=0; i<temp_clients.size(); ++i ) 00426 if ( temp_clients[i]->isEnabled() ) 00427 temp_clients[i]->initEvent(); 00428 } 00429 00431 void dispatchFileDroppedEvent(const std::vector<String>& files) 00432 { 00433 makeCurrent(); 00434 std::vector< ref<UIEventListener> > temp_clients = eventListeners(); 00435 for( unsigned i=0; i<temp_clients.size(); ++i ) 00436 if ( temp_clients[i]->isEnabled() ) 00437 temp_clients[i]->fileDroppedEvent(files); 00438 } 00439 00441 const std::set<EKey>& keyboard() const { return mKeyboard; } 00442 00444 bool isKeyPressed(EKey key) const { return mKeyboard.find(key) != mKeyboard.end(); } 00445 00447 void keyPress(EKey key) { mKeyboard.insert(key); } 00448 00450 void keyRelease(EKey key) { mKeyboard.erase(key); } 00451 00453 bool isInitialized() const { return mIsInitialized; } 00454 00456 int textureUnitCount() const { return mTextureSamplerCount; } 00457 00459 bool hasDoubleBuffer() const { return mHasDoubleBuffer; } 00460 00461 // --- render states management --- 00462 00468 void bindVAS(const IVertexAttribSet* vas, bool use_vbo, bool force); 00469 00471 void applyEnables( const EnableSet* cur ); 00472 00474 void applyRenderStates( const RenderStateSet* cur, const Camera* camera ); 00475 00477 void resetEnables(); 00478 00480 void resetRenderStates(); 00481 00483 void setDefaultRenderState(const RenderStateSlot& rs_slot) 00484 { 00485 mDefaultRenderStates[rs_slot.type()] = rs_slot; 00486 // if we are in the default render state then apply it immediately 00487 if (!mCurrentRenderStateSet->hasKey(rs_slot.type())) 00488 { 00489 mDefaultRenderStates[rs_slot.type()].apply(NULL, this); VL_CHECK_OGL(); 00490 } 00491 } 00492 00494 const RenderStateSlot& defaultRenderState(ERenderState rs) { return mDefaultRenderStates[rs]; } 00495 00497 void resetContextStates(EResetContextStates start_or_finish); 00498 00500 void setTexUnitBinding(int unit_i, ETextureDimension target) 00501 { 00502 VL_CHECK(unit_i <= VL_MAX_TEXTURE_UNITS); 00503 mTexUnitBinding[unit_i] = target; 00504 } 00505 00507 ETextureDimension texUnitBinding(int unit_i) const 00508 { 00509 VL_CHECK(unit_i <= VL_MAX_TEXTURE_UNITS); 00510 return mTexUnitBinding[unit_i]; 00511 } 00512 00514 static bool areUniformsColliding(const UniformSet* u1, const UniformSet* u2); 00515 00534 bool isCleanState(bool verbose); 00535 00536 public: 00537 // constant color 00538 const fvec3& normal() const { return mNormal; } 00539 const fvec4& color() const { return mColor; } 00540 const fvec3& secondaryColor() const { return mSecondaryColor; } 00541 const fvec4& vertexAttribValue(int i) const { VL_CHECK(i<VL_MAX_GENERIC_VERTEX_ATTRIB); return mVertexAttribValue[i]; } 00542 00543 protected: 00544 ref<Framebuffer> mLeftFramebuffer; 00545 ref<Framebuffer> mRightFramebuffer; 00546 std::vector< ref<FramebufferObject> > mFramebufferObject; 00547 std::vector< ref<UIEventListener> > mEventListeners; 00548 std::set<EKey> mKeyboard; 00549 OpenGLContextFormat mGLContextInfo; 00550 int mMaxVertexAttrib; 00551 int mTextureSamplerCount; 00552 bool mMouseVisible; 00553 bool mContinuousUpdate; 00554 bool mIgnoreNextMouseMoveEvent; 00555 bool mFullscreen; 00556 bool mHasDoubleBuffer; 00557 bool mIsInitialized; 00558 std::string mExtensions; 00559 00560 // --- Render States --- 00561 00562 // default render states 00563 RenderStateSlot mDefaultRenderStates[RS_RenderStateCount]; 00564 00565 // applyEnables() 00566 ref< NaryQuickMap<EEnable, EEnable, EN_EnableCount> > mCurrentEnableSet; 00567 ref< NaryQuickMap<EEnable, EEnable, EN_EnableCount> > mNewEnableSet; 00568 00569 // applyRenderStates() 00570 ref< NaryQuickMap<ERenderState, RenderStateSlot, RS_RenderStateCount> > mCurrentRenderStateSet; 00571 ref< NaryQuickMap<ERenderState, RenderStateSlot, RS_RenderStateCount> > mNewRenderStateSet; 00572 00573 // for each texture unit tells which target has been bound last. 00574 ETextureDimension mTexUnitBinding[VL_MAX_TEXTURE_UNITS]; 00575 00576 private: 00577 struct VertexArrayInfo 00578 { 00579 VertexArrayInfo(): mBufferObject(0), mPtr(0), mState(0), mEnabled(false) {} 00580 int mBufferObject; 00581 const unsigned char* mPtr; 00582 int mState; 00583 bool mEnabled; 00584 }; 00585 00586 protected: 00587 // --- VertexAttribSet Management --- 00588 const IVertexAttribSet* mCurVAS; 00589 VertexArrayInfo mVertexArray; 00590 VertexArrayInfo mNormalArray; 00591 VertexArrayInfo mColorArray; 00592 VertexArrayInfo mSecondaryColorArray; 00593 VertexArrayInfo mFogArray; 00594 VertexArrayInfo mTexCoordArray[VL_MAX_TEXTURE_UNITS]; 00595 VertexArrayInfo mVertexAttrib[VL_MAX_GENERIC_VERTEX_ATTRIB]; 00596 00597 // save and restore constant attributes 00598 fvec3 mNormal; 00599 fvec4 mColor; 00600 fvec3 mSecondaryColor; 00601 fvec4 mVertexAttribValue[VL_MAX_GENERIC_VERTEX_ATTRIB]; 00602 00603 private: 00604 void setupDefaultRenderStates(); 00605 }; 00606 // ---------------------------------------------------------------------------- 00607 } 00608 00609 #endif