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