From 4357cb87f6f9da9b4b0c8e46763233a9ea7fb59a Mon Sep 17 00:00:00 2001 From: ansgar <ansgar@5a81b35b-ba03-0410-adc8-b2c5c5119f08> Date: Sat, 17 Apr 2010 04:42:25 +0000 Subject: [PATCH] rewrote offscreen buffer (for glx, stubs for cgl and wgl), fixing scene export added high-level SetOutline interface to gfx obj, added outline func to gfx entity fixed cylindrical helix and flat strand mode (again, perhaps last time) synchronized/fixed ost imports in init_cl.py and base/__init__.py tweaked multisample initialization on QGLWidget added several shortcut properties to gfx::Scene in python wrapper added query aliases for cname (chain) and rtype=ext (rtype=strand) git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2034 5a81b35b-ba03-0410-adc8-b2c5c5119f08 --- modules/gfx/pymod/export_scene.cc | 44 +- modules/gfx/pymod/glwin_base_proxy.hh | 3 + modules/gfx/src/CMakeLists.txt | 16 +- modules/gfx/src/bitmap_io.cc | 8 +- modules/gfx/src/entity.cc | 17 +- modules/gfx/src/gfx_node.cc | 6 + modules/gfx/src/gfx_node.hh | 1 + modules/gfx/src/gfx_object.cc | 6 + modules/gfx/src/gfx_object.hh | 5 +- modules/gfx/src/glwin_base.hh | 4 + modules/gfx/src/impl/cartoon_renderer.cc | 408 ++++++++++--------- modules/gfx/src/impl/cartoon_renderer.hh | 12 +- modules/gfx/src/impl/cgl_offscreen_buffer.cc | 131 ++++++ modules/gfx/src/impl/cgl_offscreen_buffer.hh | 58 +++ modules/gfx/src/impl/entity_detail.cc | 2 + modules/gfx/src/impl/entity_detail.hh | 15 +- modules/gfx/src/impl/entity_renderer.hh | 2 + modules/gfx/src/impl/glx_offscreen_buffer.cc | 162 ++++++++ modules/gfx/src/impl/glx_offscreen_buffer.hh | 62 +++ modules/gfx/src/impl/wgl_offscreen_buffer.cc | 32 ++ modules/gfx/src/impl/wgl_offscreen_buffer.hh | 59 +++ modules/gfx/src/offscreen_buffer.cc | 400 ------------------ modules/gfx/src/offscreen_buffer.hh | 96 ++--- modules/gfx/src/scene.cc | 130 ++++-- modules/gfx/src/scene.hh | 13 +- modules/gfx/src/vertex_array.cc | 6 +- modules/gui/src/gl_canvas.cc | 7 +- modules/gui/src/gl_canvas.hh | 2 + modules/gui/src/gl_win.cc | 16 +- modules/mol/base/src/property_id.cc | 1 + modules/mol/base/src/query_state.cc | 4 +- scripts/init_cl.py | 14 +- 32 files changed, 997 insertions(+), 745 deletions(-) create mode 100644 modules/gfx/src/impl/cgl_offscreen_buffer.cc create mode 100644 modules/gfx/src/impl/cgl_offscreen_buffer.hh create mode 100644 modules/gfx/src/impl/glx_offscreen_buffer.cc create mode 100644 modules/gfx/src/impl/glx_offscreen_buffer.hh create mode 100644 modules/gfx/src/impl/wgl_offscreen_buffer.cc create mode 100644 modules/gfx/src/impl/wgl_offscreen_buffer.hh delete mode 100644 modules/gfx/src/offscreen_buffer.cc diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc index 9cae54473..e39c87232 100644 --- a/modules/gfx/pymod/export_scene.cc +++ b/modules/gfx/pymod/export_scene.cc @@ -33,7 +33,6 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(scene_autoslab_overloads, BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(scene_export_pov_overloads, Scene::ExportPov, 1,2) void (Scene::*apply)(const InputEvent&, bool)=&Scene::Apply; -namespace { Scene* get_scene() { @@ -49,15 +48,19 @@ GfxObjP scene_getitem(Scene* scene, const String& item) return scene->operator[](item); } +void set_offscreen_mode() +{ + Scene::Instance().SetOffscreenMode(); } -} +} // anon ns + void export_Scene() { def("Scene",get_scene,return_value_policy<reference_existing_object>()); - def("set_offscreen_mode",&Scene::SetOffscreenMode); + def("set_offscreen_mode",set_offscreen_mode); // will be removed... def("PickAtom", &pick_atom); @@ -91,16 +94,9 @@ void export_Scene() .def("RenderGL", &Scene::RenderGL) .def("Resize", &Scene::Resize) .def("SetBackground", &Scene::SetBackground) - .add_property("center", &Scene::GetCenter, &Scene::SetCenter) - .add_property("near", &Scene::GetNear, &Scene::SetNear) - .add_property("far", &Scene::GetFar, &Scene::SetFar) .def("SetNearFar",&Scene::SetNearFar) .def("SetFog",&Scene::SetFog) .def("SetFogColor",&Scene::SetFogColor) - .add_property("fog_near_offset", &Scene::GetFogNearOffset, - &Scene::SetFogNearOffset) - .add_property("fog_far_offset", &Scene::GetFogFarOffset, - &Scene::SetFogFarOffset) .def("SetFOV",&Scene::SetFOV) .def("GetFOV",&Scene::GetFOV) .def("SetFogOffsets",&Scene::SetFogOffsets) @@ -128,8 +124,34 @@ void export_Scene() .def("SetShadow",&Scene::SetShadow) .def("SetShadowQuality",&Scene::SetShadowQuality) .def("AttachObserver",&Scene::AttachObserver) + .def("__getitem__",scene_getitem) + .add_property("bg", + &Scene::GetBackground, + &Scene::SetBackground) + .add_property("center", &Scene::GetCenter, &Scene::SetCenter) + .add_property("near", &Scene::GetNear, &Scene::SetNear) + .add_property("far", &Scene::GetFar, &Scene::SetFar) + .add_property("fov", &Scene::GetFOV, &Scene::SetFOV) + .add_property("fog", &Scene::GetFog, &Scene::SetFog) + .add_property("fogcol", &Scene::GetFogColor, &Scene::SetFogColor) + .add_property("fogno", + &Scene::GetFogNearOffset, + &Scene::SetFogNearOffset) + .add_property("fogfo", + &Scene::GetFogFarOffset, + &Scene::SetFogFarOffset) + .add_property("smode", + &Scene::GetSelectionMode, + &Scene::SetSelectionMode) + // deprecated python properties! .add_property("selection_mode", &Scene::GetSelectionMode, &Scene::SetSelectionMode) - .def("__getitem__",scene_getitem) + .add_property("fog_near_offset", + &Scene::GetFogNearOffset, + &Scene::SetFogNearOffset) + .add_property("fog_far_offset", + &Scene::GetFogFarOffset, + &Scene::SetFogFarOffset) + ; } diff --git a/modules/gfx/pymod/glwin_base_proxy.hh b/modules/gfx/pymod/glwin_base_proxy.hh index 6c73fd142..8bfea675a 100644 --- a/modules/gfx/pymod/glwin_base_proxy.hh +++ b/modules/gfx/pymod/glwin_base_proxy.hh @@ -26,6 +26,9 @@ public: virtual void StatusMessage(const String& m) { call_method<void, const String>(self, "StatusMessage", m); } + virtual bool HasMultisample() const { + return call_method<bool>(self,"HasMultisample"); + } private: PyObject* self; diff --git a/modules/gfx/src/CMakeLists.txt b/modules/gfx/src/CMakeLists.txt index c07798109..e48ee5710 100644 --- a/modules/gfx/src/CMakeLists.txt +++ b/modules/gfx/src/CMakeLists.txt @@ -89,7 +89,6 @@ set(OST_GFX_SOURCES bitmap_io.cc color.cc primitives.cc -offscreen_buffer.cc entity.cc symmetry_node.cc @@ -173,6 +172,21 @@ else() set(OST_GFX_MAP_SOURCES "") endif() +if (UNIX AND NOT APPLE) + list(APPEND OST_GFX_SOURCES impl/glx_offscreen_buffer.cc) + list(APPEND OST_GFX_IMPL_HEADERS glx_offscreen_buffer.hh) +endif() + +if (APPLE) + list(APPEND OST_GFX_SOURCES impl/cgl_offscreen_buffer.cc) + list(APPEND OST_GFX_IMPL_HEADERS cgl_offscreen_buffer.hh) +endif() + +if(WIN32) + list(APPEND OST_GFX_SOURCES impl/wgl_offscreen_buffer.cc) + list(APPEND OST_GFX_IMPL_HEADERS wgl_offscreen_buffer.hh) +endif() + if (USE_SHADER) message("Compiling with Shader Support") list(APPEND OST_GFX_SOURCES shader.cc) diff --git a/modules/gfx/src/bitmap_io.cc b/modules/gfx/src/bitmap_io.cc index 8de3d7ea0..677b602c6 100644 --- a/modules/gfx/src/bitmap_io.cc +++ b/modules/gfx/src/bitmap_io.cc @@ -38,7 +38,8 @@ void export_png(const String& filename, unsigned int width, unsigned int height, LOGN_ERROR("error opening" << filename << " for exporting"); return; } - + + LOGN_DEBUG("creating png write struct"); png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { @@ -47,6 +48,7 @@ void export_png(const String& filename, unsigned int width, unsigned int height, return; } + LOGN_DEBUG("creating png info struct"); png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); @@ -72,20 +74,24 @@ void export_png(const String& filename, unsigned int width, unsigned int height, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + LOGN_DEBUG("writing png info"); png_write_info(png_ptr, info_ptr); png_bytep* row_pointers = new png_bytep[height]; png_byte* png_data = data; + LOGN_DEBUG("assigning png row pointers"); for(uint i=0;i<height;++i){ row_pointers[height-i-1]=&png_data[i*4*width]; } + LOGN_DEBUG("writing png image"); png_write_image(png_ptr, row_pointers); delete []row_pointers; + LOGN_DEBUG("finalizing png write"); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); diff --git a/modules/gfx/src/entity.cc b/modules/gfx/src/entity.cc index f7b924c13..d6dad6987 100644 --- a/modules/gfx/src/entity.cc +++ b/modules/gfx/src/entity.cc @@ -325,16 +325,15 @@ void Entity::CustomRenderGL(RenderPass pass) e=renderer_.end(); i!=e; ++i) { impl::EntityRenderer* r=i->second; if(r->IsEnabled()){ - switch(pass) { - case STANDARD_RENDER_PASS: - case OPAQUE_RENDER_PASS: + if(pass==STANDARD_RENDER_PASS || pass==OPAQUE_RENDER_PASS) { + r->Render(pass); + if(pass==STANDARD_RENDER_PASS && omode_>0) { + r->VA().SetOutlineMode(omode_); r->Render(pass); - break; - case GLOW_RENDER_PASS: - if (r->HasSelection()) { - r->Render(pass); - } - break; + r->VA().SetOutlineMode(0); + } + } else if(pass==GLOW_RENDER_PASS && r->HasSelection()) { + r->Render(pass); } } } diff --git a/modules/gfx/src/gfx_node.cc b/modules/gfx/src/gfx_node.cc index f3a61c11e..395658e96 100644 --- a/modules/gfx/src/gfx_node.cc +++ b/modules/gfx/src/gfx_node.cc @@ -160,5 +160,11 @@ bool GfxNode::IsVisible() const return show_; } +void GfxNode::ContextSwitch() +{ + for(GfxNodeVector::iterator it =node_vector_.begin();it!=node_vector_.end();++it) { + (*it)->ContextSwitch(); + } +} }} // ns diff --git a/modules/gfx/src/gfx_node.hh b/modules/gfx/src/gfx_node.hh index 0f7ecc2d0..eb4fcc2bb 100644 --- a/modules/gfx/src/gfx_node.hh +++ b/modules/gfx/src/gfx_node.hh @@ -95,6 +95,7 @@ class DLLEXPORT_OST_GFX GfxNode: public boost::enable_shared_from_this<GfxNode> // return visibility state bool IsVisible() const; + virtual void ContextSwitch(); private: GfxNode(const GfxNode& o); diff --git a/modules/gfx/src/gfx_object.cc b/modules/gfx/src/gfx_object.cc index 54301a768..319692f50 100644 --- a/modules/gfx/src/gfx_object.cc +++ b/modules/gfx/src/gfx_object.cc @@ -148,6 +148,12 @@ void GfxObj::CustomPreRenderGL(bool flag) {} void GfxObj::CustomRenderPov(PovState& pov) {} +void GfxObj::ContextSwitch() +{ + FlagRebuild(); + GfxNode::ContextSwitch(); +} + /* this should not be necessary anymore diff --git a/modules/gfx/src/gfx_object.hh b/modules/gfx/src/gfx_object.hh index 5d8d3393b..7f4ac97c2 100644 --- a/modules/gfx/src/gfx_object.hh +++ b/modules/gfx/src/gfx_object.hh @@ -122,6 +122,8 @@ public: virtual void OnRenderModeChange(); virtual void OnGLCleanup(); + virtual void ContextSwitch(); + /// \brief change render mode virtual void SetRenderMode(RenderMode::Type m); /// \brief current render mode @@ -153,6 +155,8 @@ public: void SetLineHalo(float f); float GetLineHalo() const; + void SetOutline(unsigned int m); + // add a label at the given position void AddLabel(const String& s, const geom::Vec3& pos, const Color& col, float psize); // convenience method @@ -287,7 +291,6 @@ public: RenderMode::Type render_mode_; unsigned int debug_flags_; - private: mol::Transform transform_; bool rebuild_; bool refresh_; diff --git a/modules/gfx/src/glwin_base.hh b/modules/gfx/src/glwin_base.hh index 69ce40525..996ed2ba1 100644 --- a/modules/gfx/src/glwin_base.hh +++ b/modules/gfx/src/glwin_base.hh @@ -33,11 +33,15 @@ class DLLEXPORT_OST_GFX GLWinBase { public: virtual ~GLWinBase() {} + virtual void MakeActive() {} + virtual void DoRefresh() = 0; virtual void StatusMessage(const String& m) = 0; virtual void SetStereo(bool s) = 0; + + virtual bool HasMultisample() const = 0; }; }} diff --git a/modules/gfx/src/impl/cartoon_renderer.cc b/modules/gfx/src/impl/cartoon_renderer.cc index d95119c9f..c17c1efd8 100644 --- a/modules/gfx/src/impl/cartoon_renderer.cc +++ b/modules/gfx/src/impl/cartoon_renderer.cc @@ -46,84 +46,14 @@ void CartoonRenderer::SetForceTube(bool force_tube) force_tube_ = force_tube; } -namespace { - - void smooth_strands(SplineEntryList& spl) - { - for(unsigned int i=0;i<spl.size();++i) { - if(spl[i].type==2 || spl[i].type==3 || spl[i].type==4) { - unsigned int kstart = i++; - //kstart = std::max<unsigned int>(0,kstart-1); - for(;(spl[i].type==2 || spl[i].type==3 || spl[i].type==4) && i<spl.size();++i); - unsigned int kend = i; - //kend = std::min<unsigned int>(spl.size(),kend+2); - - if(kend>kstart) { - SplineEntry& xstart=spl[kstart]; - SplineEntry& xend=spl[kend]; - - xstart.direction = geom::Normalize(xend.position-xstart.position); - xend.direction=xstart.direction; - float invf=1.0/static_cast<float>(kend-kstart); - for(unsigned int k=kstart;k<kend;++k) { - float f = static_cast<float>(k-kstart)*invf; - spl[k].position=xstart.position+f*(xend.position-xstart.position); - spl[k].direction=xstart.direction; - geom::Vec3 tmpn=geom::Normalize(xstart.normal+f*(xend.normal-xstart.normal)); - geom::Vec3 tmpx=geom::Normalize(geom::Cross(xstart.direction,tmpn)); - spl[k].normal=geom::Normalize(geom::Cross(tmpx,xstart.direction)); - } - } - } - } - } - - typedef Eigen::Matrix<Real,3,1> EVec3; - typedef Eigen::Matrix<Real,3,3> EMat3; - typedef Eigen::Matrix<Real,1,3> ERVec3; - typedef Eigen::Matrix<Real,Eigen::Dynamic,Eigen::Dynamic> EMatX; - typedef Eigen::Matrix<Real,1,Eigen::Dynamic> ERVecX; - - ERVec3 to_eigen(const geom::Vec3& v) - { - EVec3 nrvo=EVec3::Zero(); - nrvo[0]=v[0]; nrvo[1]=v[1]; nrvo[2]=v[2]; - return nrvo; - } - - std::pair<geom::Vec3,geom::Vec3> fit_helix(const std::vector<geom::Vec3>& points) - { - if(points.size()<4) { - return std::make_pair(points.front(),points.back()); - } - geom::Vec3 cen(0.0,0.0,0.0); - for(unsigned int i=0;i<points.size();++i) cen+=points[i]; - cen/=static_cast<float>(points.size()); - - EMatX A=EMatX::Zero(points.size(),3); - for(unsigned int i=0;i<points.size();++i) { - A.row(i)=to_eigen(points[i]-cen); - } - - Eigen::SVD<EMatX> svd(A); - EMatX V=svd.matrixV(); - geom::Vec3 ax(V(0,0),V(1,0),V(2,0)); - - geom::Vec3 p1=cen+ax*(-geom::Dot(cen,ax)+geom::Dot(points.front(),ax))/geom::Length2(ax); - geom::Vec3 p2=cen+ax*(-geom::Dot(cen,ax)+geom::Dot(points.back(),ax))/geom::Length2(ax); - - return std::make_pair(p1,p2); - } - -} // ns - -void CartoonRenderer::PrepareRendering(TraceSubset& subset, +void CartoonRenderer::PrepareRendering(const TraceSubset& subset, IndexedVertexArray& va, SplineEntryListList& spline_list_list, bool is_sel) { int spline_detail=std::max((unsigned int) 1, options_->GetSplineDetail()); const Color& sel_clr=this->GetSelectionColor(); + SplineEntryListList tmp_sll; if(options_!=NULL){ va.Clear(); va.SetLighting(true); @@ -131,52 +61,20 @@ void CartoonRenderer::PrepareRendering(TraceSubset& subset, va.SetColorMaterial(true); va.SetMode(0x4); va.SetPolyMode(options_->GetPolyMode()); - spline_list_list.clear(); for (int node_list=0; node_list<subset.GetSize(); ++node_list) { // first build the spline SplineEntryList spl; const NodeListSubset& nl=subset[node_list]; - int prev_type=0; for (int i=0; i<nl.GetSize();++i) { int type=0; const NodeEntry& entry=nl[i]; if(!force_tube_) { mol::ResidueHandle resh = entry.atom.GetResidue(); mol::SecStructure sst=resh.GetSecStructure(); - mol::ResidueHandle resh2 = resh.GetNext(); - mol::SecStructure sst2=mol::SecStructure(mol::SecStructure::COIL); - if (resh2.IsValid()) { - sst2=resh2.GetSecStructure(); - } if(sst.IsHelical()) { - if(options_->GetHelixMode()==1) { - if(prev_type==5) { - type=5; // cylindrical helix - } else { - type=prev_type; - } - prev_type=5; - } else { - if(prev_type==1) { - type=1; - } else { - type=prev_type; - } - prev_type=1; - } + type=1; } else if(sst.IsExtended()) { - if(!sst2.IsExtended()) { - type=3; // end of strand - } else { - if(prev_type==2) { - type=2; - } else { - type=prev_type; - } - } - prev_type=2; - } else { - prev_type=type; + type=2; } } SplineEntry ee(entry.atom.GetPos(),entry.direction, @@ -187,14 +85,16 @@ void CartoonRenderer::PrepareRendering(TraceSubset& subset, spl.push_back(ee); } if(!spl.empty()) { - if(options_->GetStrandMode()==1) { - smooth_strands(spl); - } - spline_list_list.push_back(Spline::Generate(spl,spline_detail)); + tmp_sll.push_back(spl); } } - RebuildSplineObj(va, spline_list_list, subset, is_sel); - va.SmoothNormals(options_->GetNormalSmoothFactor()); + FudgeSplineObj(va,tmp_sll); + spline_list_list.clear(); + for(SplineEntryListList::const_iterator sit=tmp_sll.begin();sit!=tmp_sll.end();++sit) { + spline_list_list.push_back(Spline::Generate(*sit,spline_detail)); + } + RebuildSplineObj(va, spline_list_list, is_sel); + //va.SmoothNormals(options_->GetNormalSmoothFactor()); } } @@ -229,9 +129,175 @@ RenderOptionsPtr CartoonRenderer::GetOptions() return options_; } +namespace { + typedef Eigen::Matrix<Real,3,1> EVec3; + typedef Eigen::Matrix<Real,3,3> EMat3; + typedef Eigen::Matrix<Real,1,3> ERVec3; + typedef Eigen::Matrix<Real,Eigen::Dynamic,Eigen::Dynamic> EMatX; + typedef Eigen::Matrix<Real,1,Eigen::Dynamic> ERVecX; + + ERVec3 to_eigen(const geom::Vec3& v) + { + EVec3 nrvo=EVec3::Zero(); + nrvo[0]=v[0]; nrvo[1]=v[1]; nrvo[2]=v[2]; + return nrvo; + } + + std::pair<geom::Vec3,geom::Vec3> fit_helix(const std::vector<geom::Vec3>& points) + { + if(points.size()<4) { + return std::make_pair(points.front(),points.back()); + } + geom::Vec3 cen(0.0,0.0,0.0); + for(unsigned int i=0;i<points.size();++i) cen+=points[i]; + cen/=static_cast<float>(points.size()); + + EMatX A=EMatX::Zero(points.size(),3); + for(unsigned int i=0;i<points.size();++i) { + A.row(i)=to_eigen(points[i]-cen); + } + + Eigen::SVD<EMatX> svd(A); + EMatX V=svd.matrixV(); + geom::Vec3 ax(V(0,0),V(1,0),V(2,0)); + + geom::Vec3 p1=cen+ax*(-geom::Dot(cen,ax)+geom::Dot(points.front(),ax))/geom::Length2(ax); + geom::Vec3 p2=cen+ax*(-geom::Dot(cen,ax)+geom::Dot(points.back(),ax))/geom::Length2(ax); + + return std::make_pair(p1,p2); + } + +} // ns + +void CartoonRenderer::FudgeSplineObj(IndexedVertexArray& va, SplineEntryListList& olistlist) +{ + SplineEntryListList nlistlist; + SplineEntryList nlist; + + for(unsigned int llc=0;llc<olistlist.size();++llc) { + SplineEntryList olist = olistlist[llc]; + for(unsigned int lc=0;lc<olist.size();++lc) { + if(olist.at(lc).type==1 && options_->GetHelixMode()==1) { + if(options_->GetHelixMode()==1) { + // cylindrical helix + // collect all CA positions + std::vector<geom::Vec3> points; + SplineEntry tmp_end(olist.at(lc)); + unsigned int lstart=lc; + for(;lc<olist.size() && olist.at(lc).type==1;++lc) { + points.push_back(olist.at(lc).position); + } + unsigned int lend=lc-1; + if(lend-lstart<3) { + // this is a short helix, may as well not bother + for(unsigned int i=lstart;i<=lend;++i) { + nlist.push_back(olist[i]); + nlist.back().type=0; + } + } else { + // fit points to a cylinder + std::pair<geom::Vec3,geom::Vec3> cyl=fit_helix(points); + + // extend the current spline to start of cyl + geom::Vec3 cyl_dir = geom::Normalize(cyl.second-cyl.first); + + if(lstart>0) { + SplineEntry tmp_end(olist[lstart]); + tmp_end.type=0; + tmp_end.position=cyl.first; + tmp_end.direction=cyl_dir; + tmp_end.color1=olist[lstart-1].color1; + tmp_end.color2=olist[lstart-1].color2; + tmp_end.normal=geom::Normalize(geom::Cross(cyl_dir,geom::Cross(tmp_end.normal,cyl_dir))); + if(geom::Dot(tmp_end.normal,olist[lstart].normal)<0.0) { + tmp_end.normal=-tmp_end.normal; + } + nlist.push_back(tmp_end); + + // break nodelist + nlistlist.push_back(nlist); + nlist.clear(); + } + + if(lend+1<olist.size()) { + // and get going with an entry at the end of the cylinder + SplineEntry tmp_start(olist[lend]); + tmp_start.type=0; + tmp_start.position=cyl.second; + tmp_start.direction=cyl_dir; + tmp_start.color1=olist[lend+1].color1; + tmp_start.color2=olist[lend+1].color2; + tmp_start.normal=geom::Normalize(geom::Cross(cyl_dir,geom::Cross(tmp_start.normal,cyl_dir))); + if(geom::Dot(tmp_start.normal,olist[lstart].normal)<0.0) { + tmp_start.normal=-tmp_start.normal; + } + nlist.push_back(tmp_start); + } + + // and finally make the cylinder + va.AddCylinder(CylinderPrim(cyl.first,cyl.second, + options_->GetHelixWidth(), + olist[lstart].color1, + olist[lend].color1), + options_->GetArcDetail(),true); + } + } else { // helix mode 0 + // just copy them over + for(;lc<olist.size() && olist.at(lc).type==1;++lc) { + nlist.push_back(olist.at(lc)); + } + } + } else if(olist.at(lc).type==2) { + // strand + unsigned int kstart=nlist.size(); + unsigned int kend=kstart; + for(;lc<olist.size() && olist.at(lc).type==2;++lc,++kend) { + nlist.push_back(olist.at(lc)); + } + kend-=1; + nlist[kend].type=3; // mark end of strand + + if(options_->GetStrandMode()==1 && kend>kstart) { + nlist[kend-1].type=3; + nlist[kend].type=5; + // smooth the strands + nlist[kstart].direction = geom::Normalize(nlist[kend].position-nlist[kstart].position); + nlist[kend].direction=nlist[kstart].direction; + float invf=1.0/static_cast<float>(kend-kstart); + for(unsigned int k=kstart;k<=kend;++k) { + float f = static_cast<float>(k-kstart)*invf; + nlist[k].position=nlist[kstart].position+f*(nlist[kend].position-nlist[kstart].position); + nlist[k].direction=nlist[kstart].direction; + geom::Vec3 tmpn=geom::Normalize(nlist[kstart].normal+f*(nlist[kend].normal-nlist[kstart].normal)); + geom::Vec3 tmpx=geom::Normalize(geom::Cross(nlist[kstart].direction,tmpn)); + nlist[k].normal=geom::Normalize(geom::Cross(tmpx,nlist[kstart].direction)); + } + // break nodelist, re-start at arrow tip + if(lc+1<olist.size()) { + nlistlist.push_back(nlist); + nlist.clear(); + nlist.push_back(nlistlist.back().back()); + nlist.back().type=0; + nlist.back().color1=olist[lc+1].color1; + nlist.back().color2=olist[lc+1].color2; + } + } + } + if(lc<olist.size()) { + nlist.push_back(olist.at(lc)); + } + } + if(!nlist.empty()) { + nlistlist.push_back(nlist); + nlist.clear(); + } + } + olistlist.swap(nlistlist); +} + void CartoonRenderer::RebuildSplineObj(IndexedVertexArray& va, - SplineEntryListList& spline_list_list, - const TraceSubset& subset, bool is_sel) + const SplineEntryListList& spline_list_list, + bool is_sel) { unsigned int detail = std::min(MAX_ARC_DETAIL, std::max(options_->GetArcDetail(), @@ -243,113 +309,75 @@ void CartoonRenderer::RebuildSplineObj(IndexedVertexArray& va, options_->GetTubeRadius()*options_->GetTubeRatio()+factor, options_->GetTubeRadius()+factor, options_->GetTubeProfileType(), - 1.0)); // tube + 1.0)); // profile 0 = tube if (!force_tube_) { profiles.push_back(GetCircProfile(detail, options_->GetHelixWidth()+factor, options_->GetHelixThickness()+factor, options_->GetHelixProfileType(), - options_->GetHelixEcc())); // helix + options_->GetHelixEcc())); // profile 1 = helix profiles.push_back(GetCircProfile(detail, options_->GetStrandWidth()+factor, options_->GetStrandThickness()+factor, options_->GetStrandProfileType(), - options_->GetStrandEcc())); // strand - profiles.push_back(GetCircProfile(detail, - 0.1*options_->GetStrandWidth()+factor, - options_->GetStrandThickness()+factor, - options_->GetTubeProfileType(), - 1.0)); // arrow end, tube profile + options_->GetStrandEcc())); // profile 2 = strand + profiles.push_back(profiles.back()); // profile 3==2, strand + profiles.push_back(GetCircProfile(detail, 1.7*options_->GetStrandWidth()+factor, 1.1*options_->GetStrandThickness()+factor, options_->GetStrandProfileType(), - options_->GetStrandEcc())); // arrow start - profiles.push_back(profiles[0]); // cylindrical helix start+end == tube + options_->GetStrandEcc())); // profile 4 = arrow start + profiles.push_back(GetCircProfile(detail, + 0.01*options_->GetStrandWidth()+factor, + 1.1*options_->GetStrandThickness()+factor, + options_->GetStrandProfileType(), + options_->GetStrandEcc())); // profile 5 = arrow end + } // iterate over all spline segments - for(SplineEntryListList::iterator it=spline_list_list.begin(); + for(SplineEntryListList::const_iterator it=spline_list_list.begin(); it<spline_list_list.end();++it) { /* for each spline segment, transform the profile according to the normal and direction and assemble it together with the last transformed profile into a graphical segment */ - SplineEntryList& slist=*it; - const NodeListSubset& nl=subset[it-spline_list_list.begin()]; + SplineEntryList slist=*it; + if(slist.empty()) continue; int sit=0, send=slist.size()-spline_detail+1; - if (nl.AtStart()>0) { - sit+=nl.AtStart()*spline_detail-spline_detail/2; - } - if (nl.AtEnd()>0) { - send-=nl.AtEnd()*spline_detail-spline_detail/2; - } + //int sit=0,send=slist.size(); TraceProfile tprof1=TransformAndAddProfile(profiles,slist[sit],va); CapProfile(tprof1,slist[sit],true,va); TraceProfile tprof2; - SplineEntry& last_se=slist[send-1]; + SplineEntry last_se=slist[std::max(0,send-1)]; for (int sc=sit+1; sc<send; ++sc) { - if(slist[sc-1].type==2 && slist[sc].type==3) { - // arrow on last strand segment - // type1 is already set to 4 (Spline::Generate), - // hence just insert single bridging profile - SplineEntry se(slist[sc]); - se.type=last_se.type; - se.type1=last_se.type1; - se.type2=last_se.type2; - tprof2=TransformAndAddProfile(profiles,se, va); - AssembleProfile(tprof1,tprof2,va); - tprof1=tprof2; - // and continue with the normal profiles - } else if(slist[sc].type==5) { - // this profile is a helix in cylinder mode - SplineEntry& hstart = slist[sc]; - int istart = sc; - // skip over all helical ones - while(slist[sc].type==5 && sc<send) ++sc; - if(sc==send) sc-=1; // hack for helix at end of trace - SplineEntry& hend = slist[sc-1]; - - // fit helix into ca points - std::vector<geom::Vec3> points; - for(int i=istart;i<sc;++i) points.push_back(slist[i].position); - std::pair<geom::Vec3,geom::Vec3> cyl=fit_helix(points); - - // extend end of current trace to beginning of cylinder - // and then cap it - SplineEntry tmp_se(slist[istart]); - tmp_se.position=cyl.first; - //tmp_se.direction=geom::Normalize(cyl.second-cyl.first); - //tmp_se.normal=geom::Normalize(geom::Cross(tmp_se.direction,geom::Normalize(geom::Cross(tmp_se.normal,tmp_se.direction)))); - tprof2=TransformAndAddProfile(profiles,tmp_se, va); - AssembleProfile(tprof1,tprof2,va); - CapProfile(tprof2,tmp_se,false,va); - // add the cylinder - va.AddCylinder(CylinderPrim(cyl.first,cyl.second, - options_->GetHelixWidth(), - hstart.color1, - hend.color1), - options_->GetArcDetail(),true); - - // restart with a new cap and another extended profile - SplineEntry tmp_se2(slist[sc-1]); - tmp_se2.position=cyl.second; - //tmp_se2.direction=geom::Normalize(cyl.first-cyl.second); - //tmp_se2.normal=geom::Normalize(geom::Cross(tmp_se2.direction,geom::Normalize(geom::Cross(tmp_se2.normal,tmp_se2.direction)))); - tprof1=TransformAndAddProfile(profiles,tmp_se2, va); - CapProfile(tprof1,tmp_se2,true,va); - tprof2=TransformAndAddProfile(profiles,hend, va); - AssembleProfile(tprof1,tprof2,va); - tprof1=tprof2; - // and continue with the normal profiles + if(slist[sc].type==3) { + if(slist[sc-1].type==2) { + // boundary to arrow + SplineEntry se(slist[sc]); + tprof2=TransformAndAddProfile(profiles,se, va); + AssembleProfile(tprof1,tprof2,va); + tprof1=tprof2; + se.type=2; + se.type1=4; + se.type2=4; + tprof2=TransformAndAddProfile(profiles,se, va); + } else { + SplineEntry se(slist[sc]); + se.type1=4; + if(options_->GetStrandMode()==1) se.type2=5; + tprof2=TransformAndAddProfile(profiles,se, va); + } + } else { + tprof2=TransformAndAddProfile(profiles,slist.at(sc), va); } - tprof2=TransformAndAddProfile(profiles,slist[sc], va); AssembleProfile(tprof1,tprof2,va); tprof1=tprof2; last_se=slist[sc]; } - CapProfile(tprof1,slist[send-1],false,va); + CapProfile(tprof1,slist.at(send-1),false,va); } } @@ -357,6 +385,8 @@ void CartoonRenderer::RebuildSplineObj(IndexedVertexArray& va, TraceProfile CartoonRenderer::TransformAndAddProfile(const std::vector<TraceProfile>& profiles, const SplineEntry& se, IndexedVertexArray& va) { + assert(se.type1>=0 && se.type1<=5); + assert(se.type2>=0 && se.type2<=5); TraceProfile prof1 = profiles[se.type1]; TraceProfile prof2 = profiles[se.type2]; diff --git a/modules/gfx/src/impl/cartoon_renderer.hh b/modules/gfx/src/impl/cartoon_renderer.hh index df3e0e69b..6b2b703f2 100644 --- a/modules/gfx/src/impl/cartoon_renderer.hh +++ b/modules/gfx/src/impl/cartoon_renderer.hh @@ -50,9 +50,14 @@ public: virtual ~CartoonRenderer(); private: + void PrepareRendering(const TraceSubset& subset, IndexedVertexArray& va, + SplineEntryListList& spline_list_list, bool is_sel); + + void FudgeSplineObj(IndexedVertexArray&, SplineEntryListList&); + void RebuildSplineObj(IndexedVertexArray& va, - SplineEntryListList& spline_list_list, - const TraceSubset& subset, bool is_sel); + const SplineEntryListList& spline_list_list, + bool is_sel); void CapProfile(const impl::TraceProfile& p, const impl::SplineEntry& se, @@ -66,9 +71,6 @@ private: const SplineEntry& se, IndexedVertexArray& va); - void PrepareRendering(TraceSubset& subset, IndexedVertexArray& va, - SplineEntryListList& spline_list_list, bool is_sel); - TraceProfile GetCircProfile(unsigned int detail, float rx, float ry, unsigned int type, float ecc); bool force_tube_; diff --git a/modules/gfx/src/impl/cgl_offscreen_buffer.cc b/modules/gfx/src/impl/cgl_offscreen_buffer.cc new file mode 100644 index 000000000..4afb53956 --- /dev/null +++ b/modules/gfx/src/impl/cgl_offscreen_buffer.cc @@ -0,0 +1,131 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + Author: Marco Biasini +*/ + +#include <ost/log.hh> +#include <ost/gfx/offscreen_buffer.hh> +#include <ost/gfx/glext_include.hh> +#include <ost/gfx/scene.hh> + +namespace ost { namespace gfx { + +OffscreenBuffer::OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared): + width_(width), height_(height), valid_(false), active_(false) +{ +#if 0 + CGLPixelFormatAttribute attributes[]={ + kCGLPFAPBuffer, + kCGLPFAColorSize, CGLPixelFormatAttribute(f.cbits), + kCGLPFAAlphaSize, CGLPixelFormatAttribute(f.abits), + kCGLPFADepthSize, CGLPixelFormatAttribute(f.dbits), + CGLPixelFormatAttribute(0) + }; + GLint npix=0; + CGLError err=CGLChoosePixelFormat(attributes, &pix_format_, &npix); + if(err) { + LOGN_ERROR("error creating offscreen rendering context. " + "CGLChoosePixFormat failed:" << CGLErrorString(err)); + return; + } + // if a context exists, share resources such as shader programs and display + // lists. + + // TODO: honor if shared? + + err=CGLCreateContext(pix_format_, CGLGetCurrentContext(), &context_); + if(err) { + LOGN_ERROR("error creating offscreen rendering context. " + "CGLCreateContext failed" << CGLErrorString(err)); + return; + } + err=CGLCreatePBuffer(width, height, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, 0, + &pbuffer_); + if (err) { + LOGN_ERROR("error creating offscreen rendering context. " + "CGLCreatePBuffer failed: " << CGLErrorString(err)); + return; + } + GLint screen=0; + assert(CGLGetVirtualScreen(context_, &screen)==0); + err=CGLSetPBuffer(context_, pbuffer_, 0, 0, screen); + if (err) { + LOGN_ERROR("error creating offscreen rendering context. " + "CGLSetPBuffer failed: " << CGLErrorString(err)); + return; + } + + + valid_=true; +#endif +} + +bool OffscreenBuffer::Resize(unsigned int w, unsigned int h) +{ +#if 0 + CGLPBufferObj new_pbuffer; + CGLError err=CGLCreatePBuffer(width, height, GL_TEXTURE_RECTANGLE_EXT, + GL_RGBA, 0, &new_pbuffer); + if (err) { + LOGN_ERROR("error resizing offscreen rendering context: " + "CGLCreatePBuffer failed: " << CGLErrorString(err)); + return false; + } + GLint screen=0; + + // TODO: this assert seems dangerous and unnecessary + assert(CGLGetVirtualScreen(context_, &screen)==0); + // + + err=CGLSetPBuffer(context_, new_pbuffer, 0, 0, screen); + if (err) { + LOGN_ERROR("error resizing offscreen rendering context. " + "CGLSetPBuffer failed: " << CGLErrorString(err)); + return false; + } + CGLDestroyPBuffer(pbuffer_); + pbuffer_=new_pbuffer; + + width_=width; + height_=height; +#else + return false; +#endif +} + +bool OffscreenBuffer::MakeActive() +{ +#if 0 + if(active_) return true; + + if (CGLError err=CGLSetCurrentContext(context_)) { + LOGN_ERROR("error switching to offscreen rendering context. " + "CGLSetCurrentContext failed: " << CGLErrorString(err)); + return false; + } + return true; +#else + return false; +#endif + +} + +}} // ns diff --git a/modules/gfx/src/impl/cgl_offscreen_buffer.hh b/modules/gfx/src/impl/cgl_offscreen_buffer.hh new file mode 100644 index 000000000..1545e68a4 --- /dev/null +++ b/modules/gfx/src/impl/cgl_offscreen_buffer.hh @@ -0,0 +1,58 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_GFX_CGL_OFFSCREEN_BUFFER_HH +#define OST_GFX_CGL_OFFSCREEN_BUFFER_HH + +#include <OpenGL/OpenGL.h> + +namespace ost { namespace gfx { + +/* + cgl (apple) implementation for offscreen buffers + + Author: Marco Biasini +*/ + +class CGLOffscreenBuffer +{ +public: + CGLOffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared=true); + + bool Resize(unsigned int w, unsigned int h); + + bool MakeActive(); + + bool IsActive() {return active_;} + + bool IsValid() {return valid_;} + +private: + int width_; + int height_; + bool valid_; + bool active_; + + CGLPBufferObj pbuffer_; + CGLContextObj context_; + CGLPixelFormatObj pix_format_; +}; + +}} // ns + +#endif diff --git a/modules/gfx/src/impl/entity_detail.cc b/modules/gfx/src/impl/entity_detail.cc index 23de774e1..52f34fcab 100644 --- a/modules/gfx/src/impl/entity_detail.cc +++ b/modules/gfx/src/impl/entity_detail.cc @@ -215,6 +215,7 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub) for(int c=0;c<size;++c) { int type1=entry_list[c].type; int type2=entry_list[std::min(c+1,size-1)].type; +# if 0 //int type0=entry_list[std::max(0,c-1)].type; if(type1==2 && type2==3) { type1=2; @@ -226,6 +227,7 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub) // profile - gives visual artefacts //type2=3; } +#endif for(int d=0;d<nsub;++d) { sublist[c*nsub+d].type=entry_list[c].type; sublist[c*nsub+d].type1=type1; diff --git a/modules/gfx/src/impl/entity_detail.hh b/modules/gfx/src/impl/entity_detail.hh index 02eeeac4a..a077d2d54 100644 --- a/modules/gfx/src/impl/entity_detail.hh +++ b/modules/gfx/src/impl/entity_detail.hh @@ -115,7 +115,14 @@ struct DLLEXPORT_OST_GFX SplineEntry { color1(1.0,1.0,1.0,1.0), color2(1.0,1.0,1.0,1.0), rad(1.0), - type(0) + type(0), + type1(0), + type2(0), + frac(0.0), + v0(1.0,0.0,0.0), + v1(0.0,1.0,0.0), + v2(0.0,0.0,1.0), + nflip(false) { } SplineEntry(const geom::Vec3& p, @@ -123,7 +130,7 @@ struct DLLEXPORT_OST_GFX SplineEntry { const geom::Vec3& n, float r, const Color& c1, const Color& c2, - int t): + unsigned int t): position(p),direction(d),normal(n),color1(c1),color2(c2),rad(r),type(t), type1(t),type2(t),frac(0.0),v0(),v1(),v2(),nflip(false) { @@ -132,8 +139,8 @@ struct DLLEXPORT_OST_GFX SplineEntry { geom::Vec3 position,direction,normal; Color color1, color2; float rad; - int type; - int type1, type2; + unsigned int type; + unsigned int type1, type2; float frac; geom::Vec3 v0,v1,v2; // helper vectors bool nflip; diff --git a/modules/gfx/src/impl/entity_renderer.hh b/modules/gfx/src/impl/entity_renderer.hh index eed38872f..db0825dd5 100644 --- a/modules/gfx/src/impl/entity_renderer.hh +++ b/modules/gfx/src/impl/entity_renderer.hh @@ -160,6 +160,8 @@ public: void FlagPositionsDirty(); void Debug(unsigned int flags); + + IndexedVertexArray& VA() {return va_;} protected: virtual void SetName(const String& name); diff --git a/modules/gfx/src/impl/glx_offscreen_buffer.cc b/modules/gfx/src/impl/glx_offscreen_buffer.cc new file mode 100644 index 000000000..fc1e2b0e9 --- /dev/null +++ b/modules/gfx/src/impl/glx_offscreen_buffer.cc @@ -0,0 +1,162 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +/* + Author: Ansgar Philippsen +*/ + +#include <ost/log.hh> +#include <ost/gfx/offscreen_buffer.hh> +#include <ost/gfx/scene.hh> + +namespace ost { namespace gfx { + +OffscreenBuffer::OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared): + width_(width), height_(height), valid_(false), active_(false) +{ + LOGN_DEBUG("offscreen buffer: checking for DISPLAY"); + if(getenv("DISPLAY")==NULL) { + LOGN_ERROR("error creating offscreen rendering context: missing DISPLAY environment variable"); + return; + } + + LOGN_DEBUG("offscreen buffer: XOpenDisplay"); + dpy_ = XOpenDisplay(getenv("DISPLAY")); + if(dpy_==NULL) { + LOGN_ERROR("error creating offscreen rendering context: XOpenDisplay failed"); + return; + } + + std::vector<int> attrib_list; + attrib_list.push_back(GLX_RENDER_TYPE); + attrib_list.push_back(GLX_RGBA_BIT); + attrib_list.push_back(GLX_DRAWABLE_TYPE); + attrib_list.push_back(GLX_PBUFFER_BIT); + attrib_list.push_back(GLX_DOUBLEBUFFER); + attrib_list.push_back(False); + attrib_list.push_back(GLX_DEPTH_SIZE); + attrib_list.push_back(f.dbits); + attrib_list.push_back(GLX_RED_SIZE); + attrib_list.push_back(f.cbits); + attrib_list.push_back(GLX_GREEN_SIZE); + attrib_list.push_back(f.cbits); + attrib_list.push_back(GLX_BLUE_SIZE); + attrib_list.push_back(f.cbits); + attrib_list.push_back(GLX_ALPHA_SIZE); + attrib_list.push_back(f.abits); + attrib_list.push_back(0); + + int nelem=0; + LOGN_DEBUG("offscreen buffer: glXChooseFBConfig"); + fbconfig_ =glXChooseFBConfig(dpy_,0,&attrib_list[0],&nelem); + if(fbconfig_==0 || nelem==0) { + LOGN_ERROR("error creating offscreen rendering context: glXChooseFBConfig failed"); + return; + } + + attrib_list.clear(); + attrib_list.push_back(GLX_PBUFFER_WIDTH); + attrib_list.push_back(width_); + attrib_list.push_back(GLX_PBUFFER_HEIGHT); + attrib_list.push_back(height_); + attrib_list.push_back(0); + + LOGN_DEBUG("offscreen buffer: glXCreatePBuffer"); + pbuffer_ = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]); + if(!pbuffer_) { + LOGN_ERROR("error creating offscreen rendering context: glXCreatePBuffer failed"); + return; + } + + if(shared) { + LOGN_DEBUG("offscreen buffer: glxCreateNewContext(shared=true)"); + context_ = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, + glXGetCurrentContext(), True); + } else { + LOGN_DEBUG("offscreen buffer: glxCreateNewContext(shared=false)"); + context_ = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, + NULL, True); + + } + + if(!context_) { + LOGN_ERROR("error creating offscreen rendering context: glXCreateNewContext failed"); + glXDestroyPbuffer(dpy_, pbuffer_); + return; + } + + valid_=true; +} + +OffscreenBuffer::~OffscreenBuffer() +{ + if(valid_) { + glXDestroyContext(dpy_, context_); + glXDestroyPbuffer(dpy_, pbuffer_); + } +} + +bool OffscreenBuffer::Resize(unsigned int width, unsigned int height) +{ + std::vector<int> attrib_list; + attrib_list.push_back(GLX_PBUFFER_WIDTH); + attrib_list.push_back(width); + attrib_list.push_back(GLX_PBUFFER_HEIGHT); + attrib_list.push_back(height); + attrib_list.push_back(0); + + GLXPbuffer new_pbuffer = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]); + + if(!new_pbuffer) { + LOGN_ERROR("offscreen rendering resize failed to allocate new pbuffer"); + return false; + } + + GLXContext new_context = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, + glXGetCurrentContext(), True); + + if(!new_context) { + LOGN_ERROR("offscreen rendering resize failed to get new context"); + return false; + } + + glXDestroyContext(dpy_, context_); + glXDestroyPbuffer(dpy_, pbuffer_); + + context_=new_context; + pbuffer_=new_pbuffer; + + width_=width; + height_=height; + + return true; +} + +bool OffscreenBuffer::MakeActive() +{ + if(active_) return true; + + if(!glXMakeContextCurrent(dpy_, pbuffer_, pbuffer_, context_)) { + LOGN_ERROR("error switching to offscreen rendering context: glXMakeContextCurrent failed"); + return false; + } + return true; +} + +}} // ns diff --git a/modules/gfx/src/impl/glx_offscreen_buffer.hh b/modules/gfx/src/impl/glx_offscreen_buffer.hh new file mode 100644 index 000000000..b5ad52f3b --- /dev/null +++ b/modules/gfx/src/impl/glx_offscreen_buffer.hh @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_GFX_GLX_OFFSCREEN_BUFFER_HH +#define OST_GFX_GLX_OFFSCREEN_BUFFER_HH + +#include <stack> +#include <ost/gfx/glext_include.hh> +#include <GL/glx.h> + +namespace ost { namespace gfx { + +/* + glx implementation for offscreen buffers + + Author: Ansgar Philippsen +*/ + +class OffscreenBuffer +{ +public: + OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared=true); + ~OffscreenBuffer(); + + bool Resize(unsigned int w, unsigned int h); + + bool MakeActive(); + + bool IsActive() {return active_;} + + bool IsValid() {return valid_;} + +private: + int width_; + int height_; + bool valid_; + bool active_; + + Display* dpy_; + GLXFBConfig* fbconfig_; + GLXPbuffer pbuffer_; + GLXContext context_; +}; + +}} // ns + +#endif diff --git a/modules/gfx/src/impl/wgl_offscreen_buffer.cc b/modules/gfx/src/impl/wgl_offscreen_buffer.cc new file mode 100644 index 000000000..6c268fb14 --- /dev/null +++ b/modules/gfx/src/impl/wgl_offscreen_buffer.cc @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ + +#include <ost/gfx/offscreen_buffer.hh> + +namespace ost { namespace gfx { + +WGLOffscreenBuffer::WGLOffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared=true): + width_(width), height_(height), valid_(false), active_(false) +{} + +bool WGLOffscreenBuffer::Resize(unsigned int w, unsigned int h) {return false;} + +bool WGLOffscreenBuffer::MakeActive() {return false;} + +}} // ns diff --git a/modules/gfx/src/impl/wgl_offscreen_buffer.hh b/modules/gfx/src/impl/wgl_offscreen_buffer.hh new file mode 100644 index 000000000..4a6efda5f --- /dev/null +++ b/modules/gfx/src/impl/wgl_offscreen_buffer.hh @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2010 by the OpenStructure authors +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation; either version 3.0 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 Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this library; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +//------------------------------------------------------------------------------ +#ifndef OST_GFX_WGL_OFFSCREEN_BUFFER_HH +#define OST_GFX_WGL_OFFSCREEN_BUFFER_HH + +#include <ost/gfx/GL/wglew.h> + +namespace ost { namespace gfx { + +/* + wgl implementation for offscreen buffers +*/ + +class WGLOffscreenBuffer: public OffscreenBuffer +{ +public: + WGLOffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared=true); + + bool Resize(unsigned int w, unsigned int h); + + bool MakeActive(); + + bool IsActive() {return active_;} + + bool IsValid() {return valid_;} + +private: + int width_; + int height_; + bool valid_; + bool active_; + + HPBUFFERARB pbuffer_; + HGLRC context_; //rendering context + HGLRC old_context_; + + HDC dev_context_;//device context + HDC old_dev_context_; +}; + +}} // ns + +#endif diff --git a/modules/gfx/src/offscreen_buffer.cc b/modules/gfx/src/offscreen_buffer.cc deleted file mode 100644 index 278c77bb1..000000000 --- a/modules/gfx/src/offscreen_buffer.cc +++ /dev/null @@ -1,400 +0,0 @@ -//------------------------------------------------------------------------------ -// This file is part of the OpenStructure project <www.openstructure.org> -// -// Copyright (C) 2008-2010 by the OpenStructure authors -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License as published by the Free -// Software Foundation; either version 3.0 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 Lesser General Public License for more -// details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this library; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -//------------------------------------------------------------------------------ -/* - Authors: Ansgar Philippsen, Marco Biasini -*/ - -#include <ost/log.hh> - -#include <ost/gfx/glext_include.hh> - -#include "offscreen_buffer.hh" - -#include <ost/gfx/scene.hh> - -namespace ost { namespace gfx { - -OffscreenBuffer& OffscreenBuffer::Instance() -{ - static OffscreenBuffer instance(500,500,8,8,8,8,24); - return instance; -} - -bool OffscreenBuffer::Begin() -{ - LOGN_DEBUG("switching to offscreen rendering"); - - if(active_) return true; - - glGetIntegerv(GL_VIEWPORT,old_vp_); -#if defined(__linux__) - - old_context_ = glXGetCurrentContext(); - - if(context_ != old_context_) { - old_dr1_ = glXGetCurrentDrawable(); - old_dr2_ = glXGetCurrentReadDrawable(); - - if(!glXMakeContextCurrent(dpy_, pbuffer_, pbuffer_, context_)) { - LOGN_ERROR("error switching to offscreen rendering context: glXMakeContextCurrent failed"); - return false; - } - } -#elif defined(__APPLE__) - - old_context_=CGLGetCurrentContext(); - - if(context_ != old_context_) { - if (CGLError err=CGLSetCurrentContext(context_)) { - LOGN_ERROR("error switching to offscreen rendering context. " - "CGLSetCurrentContext failed: " << CGLErrorString(err)); - return false; - } - } -#elif defined(_WIN32) - /*old_context_ = wglGetCurrentContext(); - - if(context_ != old_context_) { - dev_context_=wglGetCurrentDC(); - if (BOOL err=wglMakeCurrent(dev_context_, context_)) { - LOGN_ERROR("error switching to offscreen rendering context. " - "wglMakeCurrent failed: "); - return false; - } - } - */ -#endif - active_=true; - return true; -} - -bool OffscreenBuffer::End() -{ - LOGN_DEBUG("switching back to normal rendering"); - - if(!active_) return true; - -#if defined(__linux__) - - if(context_ != old_context_) { - // ignore error - glXMakeContextCurrent(dpy_, old_dr1_, old_dr2_, old_context_); - } - -#elif defined(__APPLE__) - - if(context_!=old_context_) { - // ignore error - CGLSetCurrentContext(old_context_); - } - -#elif defined(_WIN32) - /* - if(context_!=old_context_) { - old_dev_context_=wglGetCurrentDC(); - wglMakeCurrent(old_dev_context_, old_context_); - } - */ -#endif - - Scene::Instance().SetViewport(old_vp_[2],old_vp_[3]); - active_=false; - return true; -} - -bool OffscreenBuffer::Resize(unsigned int width, unsigned int height) -{ -#if defined(__linux__) - - std::vector<int> attrib_list; - attrib_list.push_back(GLX_PBUFFER_WIDTH); - attrib_list.push_back(width); - attrib_list.push_back(GLX_PBUFFER_HEIGHT); - attrib_list.push_back(height); - attrib_list.push_back(0); - - GLXPbuffer new_pbuffer = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]); - - if(!new_pbuffer) { - LOGN_ERROR("offscreen rendering resize failed"); - return false; - } - - GLXContext new_context = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, - glXGetCurrentContext(), True); - - if(!new_context) { - LOGN_ERROR("offscreen rendering resize failed to get new context"); - return false; - } - - glXDestroyContext(dpy_, context_); - glXDestroyPbuffer(dpy_, pbuffer_); - - context_=new_context; - pbuffer_=new_pbuffer; - -#elif defined(__APPLE__) - CGLPBufferObj new_pbuffer; - CGLError err=CGLCreatePBuffer(width, height, GL_TEXTURE_RECTANGLE_EXT, - GL_RGBA, 0, &new_pbuffer); - if (err) { - LOGN_ERROR("error resizing offscreen rendering context: " - "CGLCreatePBuffer failed: " << CGLErrorString(err)); - return false; - } - GLint screen=0; - assert(CGLGetVirtualScreen(context_, &screen)==0); - err=CGLSetPBuffer(context_, new_pbuffer, 0, 0, screen); - if (err) { - LOGN_ERROR("error resizing offscreen rendering context. " - "CGLSetPBuffer failed: " << CGLErrorString(err)); - return false; - } - CGLDestroyPBuffer(pbuffer_); - pbuffer_=new_pbuffer; - -#elif defined(_WIN32) - /* int attribList[] = {0}; - int format = 0; - - HPBUFFERARB new_pbuffer; - new_pbuffer = wglCreatePbufferARB(dev_context_, format, width, height, attribList); - if (new_pbuffer == NULL) - { - LOGN_ERROR("Error resizing offscreen rendering context (wglCreatePbufferARB failed)\n"); - return false; - } - - dev_context_ = wglGetPbufferDCARB(new_pbuffer); - if (dev_context_ == NULL) - { - LOGN_ERROR("Unable to retrieve handle to resized pbuffer device context\n"); - return false; - } - - context_ = wglCreateContext(dev_context_); - if (context_ == NULL) - { - LOGN_ERROR("Unable to create a rendering context for the resized pbuffer\n"); - return false; - } - // - //if (!wglShareLists(old_context_, context_)) - //{ - // LOGN_ERROR("Unable to share data between resized rendering contexts\n"); - // return; - //} - */ -#endif - // nothing failed, set new width and height - width_=width; - height_=height; - return true; -} - -bool OffscreenBuffer::IsValid() const -{ - return valid_; -} - -bool OffscreenBuffer::IsActive() const -{ - return valid_; -} - -OffscreenBuffer::OffscreenBuffer(int width, int height, int r_bits, - int b_bits, int g_bits, - int a_bits, int depth_bits): - width_(width), height_(height),valid_(false) -{ - -#if defined(__linux__) - - if(getenv("DISPLAY")==NULL) { - LOGN_ERROR("error creating offscreen rendering context: missing DISPLAY environment variable"); - return; - } - dpy_ = XOpenDisplay(getenv("DISPLAY")); - if(dpy_==NULL) { - LOGN_ERROR("error creating offscreen rendering context: XOpenDisplay failed"); - return; - } - - std::vector<int> attrib_list; - attrib_list.push_back(GLX_RENDER_TYPE); - attrib_list.push_back(GLX_RGBA_BIT); - attrib_list.push_back(GLX_DRAWABLE_TYPE); - attrib_list.push_back(GLX_PBUFFER_BIT); - attrib_list.push_back(GLX_DOUBLEBUFFER); - attrib_list.push_back(False); - attrib_list.push_back(GLX_DEPTH_SIZE); - attrib_list.push_back(depth_bits); - attrib_list.push_back(GLX_RED_SIZE); - attrib_list.push_back(r_bits); - attrib_list.push_back(GLX_GREEN_SIZE); - attrib_list.push_back(g_bits); - attrib_list.push_back(GLX_BLUE_SIZE); - attrib_list.push_back(b_bits); - attrib_list.push_back(GLX_ALPHA_SIZE); - attrib_list.push_back(a_bits); - attrib_list.push_back(0); - - int nelem=0; - fbconfig_ =glXChooseFBConfig(dpy_,0,&attrib_list[0],&nelem); - if(fbconfig_==0 || nelem==0) { - LOGN_ERROR("error creating offscreen rendering context: glXChooseFBConfig failed"); - return; - } - - attrib_list.clear(); - attrib_list.push_back(GLX_PBUFFER_WIDTH); - attrib_list.push_back(width); - attrib_list.push_back(GLX_PBUFFER_HEIGHT); - attrib_list.push_back(height); - attrib_list.push_back(0); - - pbuffer_ = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]); - if(!pbuffer_) { - LOGN_ERROR("error creating offscreen rendering context: glXCreatePBuffer failed"); - return; - } - - context_ = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, - glXGetCurrentContext(), True); - if(!context_) { - LOGN_ERROR("error creating offscreen rendering context: glXCreateNewContext failed"); - return; - } - -#elif defined(__APPLE__) - CGLPixelFormatAttribute attributes[]={ - kCGLPFAPBuffer, - kCGLPFAColorSize, CGLPixelFormatAttribute(8), - kCGLPFAAlphaSize, CGLPixelFormatAttribute(8), - kCGLPFADepthSize, CGLPixelFormatAttribute(24), - CGLPixelFormatAttribute(0) - }; - GLint npix=0; - CGLError err=CGLChoosePixelFormat(attributes, &pix_format_, &npix); - if(err) { - LOGN_ERROR("error creating offscreen rendering context. " - "CGLChoosePixFormat failed:" << CGLErrorString(err)); - return; - } - // if a context exists, share resources such as shader programs and display - // lists. - err=CGLCreateContext(pix_format_, CGLGetCurrentContext(), &context_); - if(err) { - LOGN_ERROR("error creating offscreen rendering context. " - "CGLCreateContext failed" << CGLErrorString(err)); - return; - } - err=CGLCreatePBuffer(width, height, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, 0, - &pbuffer_); - if (err) { - LOGN_ERROR("error creating offscreen rendering context. " - "CGLCreatePBuffer failed: " << CGLErrorString(err)); - return; - } - GLint screen=0; - assert(CGLGetVirtualScreen(context_, &screen)==0); - err=CGLSetPBuffer(context_, pbuffer_, 0, 0, screen); - if (err) { - LOGN_ERROR("error creating offscreen rendering context. " - "CGLSetPBuffer failed: " << CGLErrorString(err)); - return; - } - -#elif defined(_WIN32) - /* - // store current windows device and rendering context - dev_context_ = wglGetCurrentDC(); - context_ = wglGetCurrentContext(); - - int format = 0; - unsigned int nformats; - int attribList[] = - { - WGL_RED_BITS_ARB, 32, - WGL_GREEN_BITS_ARB, 32, - WGL_BLUE_BITS_ARB, 32, - WGL_ALPHA_BITS_ARB, 32, - WGL_STENCIL_BITS_ARB, 8, - WGL_DEPTH_BITS_ARB, 24, - WGL_FLOAT_COMPONENTS_NV, true, - WGL_DRAW_TO_PBUFFER_ARB, true, - 0, - }; - - wglChoosePixelFormatARB(dev_context_, attribList, NULL, 1, &format, &nformats); - if (nformats == 0) - { - LOGN_ERROR("Unable to find any RGBA32 floating point pixel formats\n"); - return; - } - - // clear attribute list - //attribList[0] = 0; - - int attribs[] = { - WGL_RED_BITS_ARB, 8, - WGL_GREEN_BITS_ARB, 8, - WGL_BLUE_BITS_ARB, 8, - WGL_ALPHA_BITS_ARB, 8, - WGL_STENCIL_BITS_ARB, 8, - WGL_DEPTH_BITS_ARB, 24, - 0, - }; - - pbuffer_ = wglCreatePbufferARB(dev_context_, format, width, height, attribs); - if (pbuffer_ == NULL) - { - LOGN_ERROR("Unable to create floating point pbuffer (wglCreatePbufferARB failed)\n"); - return; - } - - old_dev_context_ = wglGetPbufferDCARB(pbuffer_); - if (dev_context_ == NULL) - { - LOGN_ERROR("Unable to retrieve handle to pbuffer device context\n"); - return; - } - - context_ = wglCreateContext(dev_context_); - if (context_ == NULL) - { - LOGN_ERROR("Unable to create a rendering context for the pbuffer\n"); - return; - } - - if (!wglShareLists(old_context_, context_)) - { - LOGN_ERROR("Unable to share data between rendering contexts\n"); - return; - } -*/ -#endif - - // nothing failed, all is good - valid_=true; - active_=false; -} - -}} diff --git a/modules/gfx/src/offscreen_buffer.hh b/modules/gfx/src/offscreen_buffer.hh index c033d8816..df2ca183f 100644 --- a/modules/gfx/src/offscreen_buffer.hh +++ b/modules/gfx/src/offscreen_buffer.hh @@ -22,86 +22,54 @@ /* Wraps GL offscreen rendering per platform - Authors: Ansgar Philippsen, Marco Biasini + boilerplate header, includes platform dependent stuff */ -#include <ost/gfx/gl_include.hh> - -#if defined(__linux__) -# include <GL/glx.h> -#elif defined(__APPLE__) -# include <OpenGL/OpenGL.h> -//#elif defined(_WIN32) -//# include <ost/gfx/GL/wglew.h> -#endif - -#ifdef Complex -# undef Complex -#endif +#include <vector> namespace ost { namespace gfx { -/// \brief offscreen management -class OffscreenBuffer { +class OffscreenBufferFormat +{ public: - - /// \brief singleton interface - static OffscreenBuffer& Instance(); + OffscreenBufferFormat(): cbits(8),abits(8),dbits(12),accum(false),multisample(false),samples(0) {} - /// \brief activate offscreen context for rendering - bool Begin(); - /// \brief switch back to normal rendering context - bool End(); - /// \ brief resize offscreen rendering context - bool Resize(unsigned int width, unsigned int height); + unsigned int cbits,abits,dbits; // color, alpha, depth bits + bool accum; + bool multisample; + unsigned int samples; +}; - /// \brief returns true if offscreen rendering context is available - bool IsValid() const; +}} // ns - /// \brief returns true between Begin/End bracket - bool IsActive() const; +/* + instead of creating an abstract base class and + making runtime polymorphic classes for each + platform, we do a bit more typing and copy + the minimal interface to each of the platform + specific OffscreenBuffer implementations -private: - OffscreenBuffer(int width, int height, int r_bits, int b_bits, - int g_bits, int a_bits, int depth_bits); + OffscreenBuffer interface: - OffscreenBuffer(const OffscreenBuffer& b) {} - OffscreenBuffer& operator=(const OffscreenBuffer& b) {return *this;} - - int width_; - int height_; - bool valid_; - bool active_; + OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared=true); + bool Resize(unsigned int w, unsigned int h); + bool MakeActive(); + bool IsActive(); + bool IsValid(); +*/ #if defined(__linux__) - Display* dpy_; - GLXFBConfig* fbconfig_; - GLXPbuffer pbuffer_; - GLXContext context_; - GLXContext old_context_; - GLXDrawable old_dr1_; - GLXDrawable old_dr2_; - +#include "impl/glx_offscreen_buffer.hh" #elif defined(__APPLE__) - - CGLPBufferObj pbuffer_; - CGLContextObj context_; - CGLPixelFormatObj pix_format_; - CGLContextObj old_context_; - +#include "impl/cgl_offscreen_buffer.hh" #elif defined(_WIN32) -/* HPBUFFERARB pbuffer_; - HGLRC context_; //rendering context - HGLRC old_context_; - - HDC dev_context_;//device context - HDC old_dev_context_; - */ +#include "impl/wgl_offscreen_buffer.hh" +#else +#error platform not found for offscreen rendering #endif - - GLint old_vp_[4]; -}; -}} +#ifdef Complex +# undef Complex +#endif #endif diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc index 7e6ee6e2c..4a315636d 100644 --- a/modules/gfx/src/scene.cc +++ b/modules/gfx/src/scene.cc @@ -42,7 +42,6 @@ #include "gl_helper.hh" #include <ost/config.hh> -#include "offscreen_buffer.hh" #include "scene.hh" #include "input.hh" #include "gfx_node.hh" @@ -51,6 +50,7 @@ #include "bitmap_io.hh" #include "entity.hh" #include "povray.hh" +#include "offscreen_buffer.hh" #if OST_SHADER_SUPPORT_ENABLED # include "shader.hh" @@ -115,6 +115,7 @@ Scene::Scene(): texture_id_(), auto_autoslab_(true), offscreen_flag_(false), + main_offscreen_buffer_(0), selection_mode_(1), test_flag_(false), tmp_tex_(), @@ -143,6 +144,11 @@ void Scene::SetFog(bool f) RequestRedraw(); } +bool Scene::GetFog() const +{ + return fog_flag_; +} + void Scene::SetFogColor(const Color& c) { GLfloat fogc[]={c.Red(),c.Green(),c.Blue(),1.0}; @@ -151,6 +157,11 @@ void Scene::SetFogColor(const Color& c) RequestRedraw(); } +Color Scene::GetFogColor() const +{ + return fog_color_; +} + void Scene::SetShadow(bool f) { shadow_flag_=f; @@ -181,9 +192,10 @@ void set_light_dir(Vec3 ld) void Scene::InitGL() { - LOG_DEBUG("scene: initializing GL state" << std::endl); + LOGN_DEBUG("scene: initializing GL state"); #if OST_SHADER_SUPPORT_ENABLED + LOGN_DEBUG("scene: shader pre-gl"); Shader::Instance().PreGLInit(); #endif @@ -234,9 +246,29 @@ void Scene::InitGL() glShadeModel(GL_SMOOTH); // line and point anti-aliasing + +#if OST_SHADER_SUPPORT_ENABLED + GLint mbufs,msamples; + glGetIntegerv(GL_SAMPLE_BUFFERS, &mbufs); + glGetIntegerv(GL_SAMPLES, &msamples); + + if(mbufs>0 && msamples>0) { + LOGN_VERBOSE("enabling multisampling with: " << msamples << " samples"); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_POINT_SMOOTH); + glDisable(GL_POLYGON_SMOOTH); + glEnable(GL_MULTISAMPLE); + } else { + glEnable(GL_LINE_SMOOTH); + glDisable(GL_POINT_SMOOTH); + glDisable(GL_POLYGON_SMOOTH); + } +#else glEnable(GL_LINE_SMOOTH); glDisable(GL_POINT_SMOOTH); glDisable(GL_POLYGON_SMOOTH); +#endif + // rendering hints glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glHint(GL_FOG_HINT, GL_NICEST); @@ -249,6 +281,7 @@ void Scene::InitGL() // glDrawBuffer(GL_BACK); // initialize shaders #if OST_SHADER_SUPPORT_ENABLED + LOGN_DEBUG("scene: shader setup"); Shader::Instance().Setup(); Shader::Instance().Activate("fraglight"); @@ -278,6 +311,11 @@ void Scene::SetBackground(const Color& c) RequestRedraw(); } +Color Scene::GetBackground() const +{ + return background_; +} + Viewport Scene::GetViewport() const { Viewport vp; @@ -1124,25 +1162,6 @@ uint Scene::GetSelectionMode() const return selection_mode_; } -namespace { - -struct OffscreenSwitcher -{ - OffscreenSwitcher() - { - LOGN_TRACE("offscreen begin"); - OffscreenBuffer::Instance().Begin(); - } - - ~OffscreenSwitcher() - { - LOGN_TRACE("offscreen end"); - OffscreenBuffer::Instance().End(); - } -}; - -} // anon ns - void Scene::Export(const String& fname, unsigned int width, unsigned int height, bool transparent) { @@ -1157,37 +1176,47 @@ void Scene::Export(const String& fname, unsigned int width, return; } - offscreen_flag_=true; - LOGN_TRACE("offscreen resize"); - OffscreenBuffer::Instance().Resize(width, height); + LOGN_DEBUG("switching to offscreen rendering"); + bool old_flag=offscreen_flag_; + GLint old_vp[4]; + glGetIntegerv(GL_VIEWPORT,old_vp); try { - // ensures that context is switched back when this goes out of scope - OffscreenSwitcher offscreen_switch; + OffscreenBuffer ob(width,height,OffscreenBufferFormat(),true); + if(!ob.IsValid()) { + LOGN_ERROR("error during offscreen buffer creation"); + return; + } + + ob.MakeActive(); + offscreen_flag_=true; + root_node_->ContextSwitch(); +#if 1 #if OST_SHADER_SUPPORT_ENABLED String shader_name = Shader::Instance().GetCurrentName(); #endif - LOGN_TRACE("initializing GL"); + LOGN_DEBUG("initializing GL"); this->InitGL(); - LOGN_TRACE("setting viewport"); + LOGN_DEBUG("setting viewport"); SetViewport(width,height); - LOGN_TRACE("reseting projection"); + LOGN_DEBUG("reseting projection"); ResetProjection(); - LOGN_TRACE("updating fog settings"); + LOGN_DEBUG("updating fog settings"); update_fog(); glDrawBuffer(GL_FRONT); //this->flag_all_dirty(); #if OST_SHADER_SUPPORT_ENABLED - LOGN_TRACE("activating shader"); + LOGN_DEBUG("activating shader"); Shader::Instance().Activate(shader_name); #endif - LOGN_TRACE("doing rendering"); +#endif + LOGN_DEBUG("doing rendering"); this->RenderGL(); // make sure drawing operations are finished glFinish(); boost::shared_array<uchar> img_data(new uchar[width*height*4]); - LOGN_TRACE("setting background transparency"); + LOGN_DEBUG("setting background transparency"); if (transparent) { glPixelTransferf(GL_ALPHA_BIAS, 0.0); } else { @@ -1195,18 +1224,31 @@ void Scene::Export(const String& fname, unsigned int width, glPixelTransferf(GL_ALPHA_BIAS, 1.0); } - LOGN_TRACE("reading framebuffer pixels"); + LOGN_DEBUG("reading framebuffer pixels"); glReadBuffer(GL_FRONT); glReadPixels(0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,img_data.get()); LOGN_DEBUG("calling bitmap export"); BitmapExport(fname,ext,width,height,img_data.get()); - } catch (...) { + } catch (std::exception& e) { + LOGN_ERROR("exception during offscreen rendering: " << e.what()); + throw; // noop - } // offscreen_switch goes out of scope - offscreen_flag_=false; + } + LOGN_DEBUG("switching back to main context"); + if(main_offscreen_buffer_) { + main_offscreen_buffer_->MakeActive(); + } else if (win_) { + win_->MakeActive(); + } else { + LOGN_ERROR("erm, no context to fall back to"); + return; + } + Scene::Instance().SetViewport(old_vp[2],old_vp[3]); + offscreen_flag_=old_flag; + root_node_->ContextSwitch(); glDrawBuffer(GL_BACK); - LOGN_TRACE("updating fog"); + LOGN_DEBUG("updating fog"); update_fog(); } @@ -1552,7 +1594,17 @@ bool Scene::InOffscreenMode() const void Scene::SetOffscreenMode() { - OffscreenBuffer::Instance().Begin(); + if(main_offscreen_buffer_) return; + main_offscreen_buffer_ = new OffscreenBuffer(1000,1000,OffscreenBufferFormat(),false); + if(main_offscreen_buffer_->IsValid()) { + LOGN_DEBUG("activating offscreen buffer"); + main_offscreen_buffer_->MakeActive(); + offscreen_flag_=true; + InitGL(); + } else { + LOGN_DEBUG("offscreen buffer is not valid"); + delete main_offscreen_buffer_; + } } float Scene::ElapsedTime() const diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh index d86e46a6a..abcd7a948 100644 --- a/modules/gfx/src/scene.hh +++ b/modules/gfx/src/scene.hh @@ -46,6 +46,7 @@ namespace ost { namespace gfx { class InputEvent; +class OffscreenBuffer; typedef std::vector<SceneObserver*> SceneObserverList; @@ -92,9 +93,15 @@ class DLLEXPORT_OST_GFX Scene { /// \brief turn fog on or off void SetFog(bool f); + /// \brief check fog status + bool GetFog() const; + /// \brief set the fog color void SetFogColor(const Color& c); + /// \brief get the fog color + Color GetFogColor() const; + /// \brief turn shadow on and off void SetShadow(bool f); @@ -225,6 +232,9 @@ class DLLEXPORT_OST_GFX Scene { /// \brief set background color void SetBackground(const Color& c); + /// \brief get background color + Color GetBackground() const; + /// \brief center rotation on the given point void SetCenter(const geom::Vec3& cen); @@ -312,7 +322,7 @@ class DLLEXPORT_OST_GFX Scene { bool InOffscreenMode() const; /// \brief internal use - static void SetOffscreenMode(); + void SetOffscreenMode(); /// \brief switch into test mode (internal use) void SetTestMode(bool t); @@ -383,6 +393,7 @@ private: bool auto_autoslab_; bool offscreen_flag_; + OffscreenBuffer* main_offscreen_buffer_; uint selection_mode_; diff --git a/modules/gfx/src/vertex_array.cc b/modules/gfx/src/vertex_array.cc index 01ea30514..8ba36be18 100644 --- a/modules/gfx/src/vertex_array.cc +++ b/modules/gfx/src/vertex_array.cc @@ -368,7 +368,9 @@ void IndexedVertexArray::RenderGL() if(!initialized_) { LOGN_DUMP("initializing vertex array lists"); #if OST_SHADER_SUPPORT_ENABLED - glGenBuffers(7,buffer_id_); + if(!Scene::Instance().InOffscreenMode()) { + glGenBuffers(7,buffer_id_); + } #endif outline_mat_dlist_=glGenLists(1); initialized_=true; @@ -390,6 +392,7 @@ void IndexedVertexArray::RenderGL() use_buff=prep_buff(); } if(!use_buff) { + LOGN_DUMP("buffer not available"); glBindBuffer(GL_ARRAY_BUFFER,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); } else { @@ -1095,6 +1098,7 @@ void IndexedVertexArray::copy(const IndexedVertexArray& va) bool IndexedVertexArray::prep_buff() { + if(Scene::Instance().InOffscreenMode()) return false; #if OST_SHADER_SUPPORT_ENABLED glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); diff --git a/modules/gui/src/gl_canvas.cc b/modules/gui/src/gl_canvas.cc index ebcbd0d38..0010c895a 100644 --- a/modules/gui/src/gl_canvas.cc +++ b/modules/gui/src/gl_canvas.cc @@ -46,7 +46,7 @@ namespace ost { namespace gui { using gfx::Scene; GLCanvas::GLCanvas(GLWin* gl_win, QWidget* parent, const QGLFormat& f): - QGLWidget(f, parent), + QGLWidget(f,parent), glwin_(gl_win) { if(!isValid()) return; @@ -61,6 +61,11 @@ GLCanvas::GLCanvas(GLWin* gl_win, QWidget* parent, const QGLFormat& f): SLOT(RequestContextMenu(const QPoint&))); } +void GLCanvas::MakeActive() +{ + makeCurrent(); +} + void GLCanvas::DoRefresh() { refresh_=true; diff --git a/modules/gui/src/gl_canvas.hh b/modules/gui/src/gl_canvas.hh index 87137dcc1..631aa624d 100644 --- a/modules/gui/src/gl_canvas.hh +++ b/modules/gui/src/gl_canvas.hh @@ -51,9 +51,11 @@ public: const QGLFormat& f = QGLFormat::defaultFormat()); // gfx::GLWinBase interface + virtual void MakeActive(); virtual void DoRefresh(); virtual void StatusMessage(const String& m); virtual void SetStereo(bool s); + virtual bool HasMultisample() const {return format().sampleBuffers();} // central point for sending input to the gfx layer void OnTransform(gfx::InputCommand, int indx, diff --git a/modules/gui/src/gl_win.cc b/modules/gui/src/gl_win.cc index 7e4a6948f..693a9197a 100644 --- a/modules/gui/src/gl_win.cc +++ b/modules/gui/src/gl_win.cc @@ -56,7 +56,7 @@ GLWin::GLWin(QWidget* p): if(gl_canvas_->isValid()) { break; // format is fine } else { - delete gl_canvas_; // delete this canvas and try less sophisticated format + delete gl_canvas_; // delete this canvas and try a less sophisticated format } } @@ -68,12 +68,14 @@ GLWin::GLWin(QWidget* p): this->SetInternalWidget(main); gfx::Scene::Instance().AttachObserver(this); QGLFormat format = gl_canvas_->format(); - LOGN_MESSAGE("GLCanvas created with rbits=" << format.redBufferSize() - << " gbits=" << format.greenBufferSize() << " bbits=" - << format.blueBufferSize() << " abits=" - << format.alphaBufferSize() << " dbits=" - << format.depthBufferSize() << " accumbits=" - << format.accumBufferSize()); + LOGN_VERBOSE("GLCanvas created with rbits=" << format.redBufferSize() + << " gbits=" << format.greenBufferSize() + << " bbits=" << format.blueBufferSize() + << " abits=" << format.alphaBufferSize() + << " dbits=" << format.depthBufferSize() + << " accumbits=" << format.accumBufferSize() + << " multisample=" << format.sampleBuffers() + << " with samples=" << format.samples()); main->setCentralWidget(gl_canvas_); connect(gl_canvas_, SIGNAL(ReleaseFocus()), this, SIGNAL(ReleaseFocus())); connect(&ToolManager::Instance(), SIGNAL(ActiveToolChanged(Tool*)), this, SLOT(ActiveToolChanged(Tool*))); diff --git a/modules/mol/base/src/property_id.cc b/modules/mol/base/src/property_id.cc index 790d62833..ed19a4f3e 100644 --- a/modules/mol/base/src/property_id.cc +++ b/modules/mol/base/src/property_id.cc @@ -44,6 +44,7 @@ struct Properties : public boost::spirit::symbols<Prop> { ("z",Prop(Prop::AZ, Prop::FLOAT, Prop::ATOM)) ("occ",Prop(Prop::OCC, Prop::FLOAT, Prop::ATOM)) ("cname",Prop(Prop::CNAME, Prop::STRING, Prop::CHAIN)) + ("chain",Prop(Prop::CNAME, Prop::STRING, Prop::CHAIN)) ("ishetatm",Prop(Prop::ISHETATM, Prop::INT, Prop::ATOM)) ("abfac", Prop(Prop::ABFAC, Prop::FLOAT, Prop::ATOM)) ("rbfac", Prop(Prop::RBFAC, Prop::FLOAT, Prop::RESIDUE)) diff --git a/modules/mol/base/src/query_state.cc b/modules/mol/base/src/query_state.cc index a8e3199bc..004af514f 100644 --- a/modules/mol/base/src/query_state.cc +++ b/modules/mol/base/src/query_state.cc @@ -215,10 +215,12 @@ boost::logic::tribool QueryState::EvalResidue(const impl::ResidueImplPtr& r) { bool b=false; if (p=="helix") { b=r->GetSecStructure().IsHelical(); - } else if (p=="ext") { + } else if (p=="ext" || p=="strand") { b=r->GetSecStructure().IsExtended(); } else if (p=="coil") { b=r->GetSecStructure().IsCoil(); + } else if (p=="*") { + b=true; } s_[*i]=ss.comp_op==COP_EQ ? b : !b; } else { diff --git a/scripts/init_cl.py b/scripts/init_cl.py index f67159fc8..e8874c63f 100644 --- a/scripts/init_cl.py +++ b/scripts/init_cl.py @@ -4,16 +4,10 @@ if platform.machine()=='x86_64': else: sys.path.insert(0,os.getenv('DNG_ROOT')+'/lib/openstructure') -from ost import io, mol, seq, conop, geom +#from ost import io, mol, seq, conop, geom +from ost import * import ost -try: - from ost import img -except ImportError: - pass -try: - from ost import gfx -except ImportError: - pass + ost.SetPrefixPath(os.getenv('DNG_ROOT')) def _InitRuleBasedBuilder(): compound_lib_path=os.path.join(ost.GetSharedDataPath(), 'compounds.chemlib') @@ -31,7 +25,7 @@ HistoryFile=os.path.expanduser('~/.ost_history') InGUIMode=False -#gfx.set_offscreen_mode() +gfx.set_offscreen_mode() sys.ps1='ost> ' sys.ps2='..... ' print '' -- GitLab