From e5eb661b0053e250942200ed43c6320ef860e34c Mon Sep 17 00:00:00 2001
From: ansgar <ansgar@5a81b35b-ba03-0410-adc8-b2c5c5119f08>
Date: Wed, 28 Apr 2010 14:53:17 +0000
Subject: [PATCH] reverted all changes to the gfx module since r2007, except
 map_iso downsampling

moved all these features to the new_gfx branch, including

cpk fast spheres
helix cylinders and flat beta strands
ambient occlusion
improved scene export and offscreen buffer handling
fixes to shaders
new GfxObj and GfxObjBase re-organization
backbone trace/spline re-write
vertex array fixes
multisample extension detection



git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2130 5a81b35b-ba03-0410-adc8-b2c5c5119f08
---
 modules/gfx/pymod/color_by_def.hh             | 177 ++---
 modules/gfx/pymod/export_entity.cc            |  12 -
 modules/gfx/pymod/export_gfx_obj.cc           |  97 +--
 modules/gfx/pymod/export_render_options.cc    |   6 -
 modules/gfx/pymod/export_scene.cc             |  43 +-
 modules/gfx/pymod/glwin_base_proxy.hh         |   3 -
 modules/gfx/pymod/wrap_gfx.cc                 |  13 +-
 modules/gfx/src/CMakeLists.txt                |  17 +-
 modules/gfx/src/bitmap_io.cc                  |   8 +-
 modules/gfx/src/entity.cc                     |  68 +-
 modules/gfx/src/entity.hh                     |   9 -
 modules/gfx/src/gfx_node.cc                   |   6 -
 modules/gfx/src/gfx_node.hh                   |   1 -
 modules/gfx/src/gfx_object.cc                 | 747 +++++++++++-------
 modules/gfx/src/gfx_object.hh                 | 217 +++--
 modules/gfx/src/gfx_prim.hh                   |  12 +-
 modules/gfx/src/glwin_base.hh                 |   4 -
 modules/gfx/src/impl/backbone_trace.cc        | 257 +++---
 modules/gfx/src/impl/backbone_trace.hh        | 104 ++-
 modules/gfx/src/impl/cartoon_renderer.cc      | 322 ++------
 modules/gfx/src/impl/cartoon_renderer.hh      |  27 +-
 modules/gfx/src/impl/debug_renderer.cc        |  11 +-
 modules/gfx/src/impl/debug_renderer.hh        |   2 +-
 modules/gfx/src/impl/entity_detail.cc         | 186 +++--
 modules/gfx/src/impl/entity_detail.hh         |  35 +-
 modules/gfx/src/impl/entity_renderer.hh       |   9 +-
 modules/gfx/src/impl/line_trace_renderer.cc   |  65 +-
 modules/gfx/src/impl/line_trace_renderer.hh   |   9 +-
 modules/gfx/src/impl/sline_renderer.cc        |  41 +-
 modules/gfx/src/impl/sline_renderer.hh        |   9 +-
 modules/gfx/src/impl/trace_renderer.cc        | 177 ++++-
 modules/gfx/src/impl/trace_renderer.hh        |  19 +-
 modules/gfx/src/impl/trace_renderer_base.cc   |  78 +-
 modules/gfx/src/impl/trace_renderer_base.hh   |  18 +-
 modules/gfx/src/offscreen_buffer.hh           |  96 ++-
 modules/gfx/src/prim_list.cc                  |  23 +-
 modules/gfx/src/prim_list.hh                  |   8 -
 .../render_options/cartoon_render_options.cc  |  31 +-
 .../render_options/cartoon_render_options.hh  |   7 -
 .../src/render_options/cpk_render_options.cc  |   2 +-
 modules/gfx/src/render_pass.hh                |   4 +-
 modules/gfx/src/scene.cc                      | 281 ++-----
 modules/gfx/src/scene.hh                      |  36 +-
 modules/gfx/src/shader/fraglight_lf_fs.glsl   |  30 +-
 modules/gfx/src/surface.cc                    |  84 +-
 modules/gfx/src/vertex_array.cc               |  70 +-
 modules/gfx/src/vertex_array.hh               |  34 +-
 modules/gui/pymod/scene/cpk_widget.py         |  27 +-
 modules/gui/pymod/scene/hsc_widget.py         |  61 +-
 49 files changed, 1796 insertions(+), 1807 deletions(-)

diff --git a/modules/gfx/pymod/color_by_def.hh b/modules/gfx/pymod/color_by_def.hh
index d45bb327e..1c4643acd 100644
--- a/modules/gfx/pymod/color_by_def.hh
+++ b/modules/gfx/pymod/color_by_def.hh
@@ -22,16 +22,13 @@
 #include <ost/config.hh>
 #include <ost/gfx/gfx_object.hh>
 
-#if OST_IMG_ENABLED
-#include <ost/img/alg/stat.hh>
-#endif
-
 using namespace ost;
 using namespace ost::gfx;
 
 namespace ost_gfx {
 
-inline void color_by_e0(GfxObj* go,
+#if OST_IMG_ENABLED
+inline void color_by_01(GfxObj* go,
                 const mol::EntityView& ev, 
                 const String& prop,
                 const Gradient& g, float minv, float maxv)
@@ -39,141 +36,117 @@ inline void color_by_e0(GfxObj* go,
   go->ColorBy(ev,prop,g,minv,maxv);
 }
 
-inline void color_by_e1(GfxObj* go,
-			const mol::EntityView& ev, 
-			const String& prop,
-			const Color& c1, const Color& c2, float minv, float maxv)
+inline void color_by_02(GfxObj* go,
+                const ::img::MapHandle& mh, 
+                const String& prop,
+                const Gradient& g, float minv, float maxv)
 {
-  Gradient g;
-  g.SetColorAt(0.0,c1);
-  g.SetColorAt(1.0,c2);
-  go->ColorBy(ev,prop,g,minv,maxv);
+  go->ColorBy(mh,prop,g,minv,maxv);
 }
 
-inline void color_by_e2(GfxObj* go,
-			const mol::EntityHandle& eh, 
-			const String& prop,
-			const Gradient& g, float minv, float maxv)
+
+inline void color_by_11(GfxObj* go,
+                 const ::img::MapHandle& mh, 
+                 const String& prop,
+                 const Gradient& g)
 {
-  go->ColorBy(eh.CreateFullView(),prop,g,minv,maxv);
+  go->ColorBy(mh,prop,g);
 }
 
-inline void color_by_e3(GfxObj* go,
-			const mol::EntityHandle& eh, 
-			const String& prop,
-			const Color& c1, const Color& c2, float minv, float maxv)
+inline void color_by_12(GfxObj* go,
+                 const ::img::MapHandle& mh, 
+                 const String& prop,
+                 const Color& c1, const Color& c2)
 {
-  Gradient g;
-  g.SetColorAt(0.0,c1);
-  g.SetColorAt(1.0,c2);
-  go->ColorBy(eh.CreateFullView(),prop,g,minv,maxv);
+  go->ColorBy(mh,prop,c1,c2);
 }
 
-inline void color_by_e4(GfxObj* go,
-			const mol::EntityView& ev, 
-			const String& prop,
-			const Gradient& g)
+
+inline void color_by_04(GfxObj* go,
+                const ::img::MapHandle& mh, 
+                const String& prop,
+                const Color& c1, const Color& c2, float minv, float maxv)
 {
-  std::pair<float,float> minmax = ev.GetMinMax(prop);
-  go->ColorBy(ev,prop,g,minmax.first, minmax.second);
+  go->ColorBy(mh,prop,c1,c2,minv,maxv);
 }
 
-inline void color_by_e5(GfxObj* go,
-			const mol::EntityView& ev, 
-			const String& prop,
-			const Color& c1, const Color& c2)
+#endif
+
+inline void color_by_03(GfxObj* go,
+                const mol::EntityView& ev, 
+                const String& prop,
+                const Color& c1, const Color& c2, float minv, float maxv)
 {
-  Gradient g;
-  g.SetColorAt(0.0,c1);
-  g.SetColorAt(1.0,c2);
-  std::pair<float,float> minmax = ev.GetMinMax(prop);
-  go->ColorBy(ev,prop,g,minmax.first, minmax.second);
+  go->ColorBy(ev,prop,c1,c2,minv,maxv);
 }
 
-inline void color_by_e6(GfxObj* go,
-			const mol::EntityHandle& eh, 
-			const String& prop,
-			const Gradient& g)
+
+
+inline void color_by_05(GfxObj* go,
+                const mol::EntityHandle& eh, 
+                const String& prop,
+                const Gradient& g, float minv, float maxv)
 {
-  color_by_e4(go,eh.CreateFullView(),prop,g);
+  go->ColorBy(eh,prop,g,minv,maxv);
 }
 
-inline void color_by_e7(GfxObj* go,
-			const mol::EntityHandle& eh, 
-			const String& prop,
-			const Color& c1, const Color& c2)
+inline void color_by_06(GfxObj* go,
+                const mol::EntityHandle& eh, 
+                const String& prop,
+                const Color& c1, const Color& c2, float minv, float maxv)
 {
-  color_by_e5(go,eh.CreateFullView(),prop,c1,c2);
+  go->ColorBy(eh,prop,c1,c2,minv,maxv);
 }
 
-#if OST_IMG_ENABLED
-inline void color_by_m0(GfxObj* go,
-			const ::img::MapHandle& mh, 
-			const String& prop,
-			const Gradient& g, float minv, float maxv)
-{
-  go->ColorBy(mh,prop,g,minv,maxv);
+inline void color_by_07(GfxObj* go,
+                const mol::EntityView& ev, 
+                const String& prop,
+                const Gradient& g){
+  go->ColorBy(ev,prop,g);
 }
 
-inline void color_by_m1(GfxObj* go,
-			  const ::img::MapHandle& mh, 
-			  const String& prop,
-			  const Gradient& g)
+inline void color_by_08(GfxObj* go,
+                const mol::EntityView& ev, 
+                const String& prop,
+                const Color& c1, const Color& c2)
 {
-  ost::img::alg::Stat stat;
-  mh.Apply(stat);
-  float min = static_cast<float>(stat.GetMinimum());
-  float max = static_cast<float>(stat.GetMaximum());
-  std::pair<float,float> minmax = std::make_pair(min,max);
-  go->ColorBy(mh,prop,g,minmax.first, minmax.second);
+  go->ColorBy(ev,prop,c1,c2);
 }
 
-inline void color_by_m2(GfxObj* go,
-			const ::img::MapHandle& mh, 
-			const String& prop,
-			const Color& c1, const Color& c2)
+inline void color_by_09(GfxObj* go,
+                const mol::EntityHandle& ev, 
+                const String& prop,
+                const Gradient& g)
 {
-  Gradient g;
-  g.SetColorAt(0.0,c1);
-  g.SetColorAt(1.0,c2);
-  ost::img::alg::Stat stat;
-  mh.Apply(stat);
-  float min = static_cast<float>(stat.GetMinimum());
-  float max = static_cast<float>(stat.GetMaximum());
-  std::pair<float,float> minmax = std::make_pair(min,max);
-  go->ColorBy(mh,prop,g,minmax.first, minmax.second);
+  go->ColorBy(ev,prop,g);
 }
 
-inline void color_by_m3(GfxObj* go,
-			const ::img::MapHandle& mh, 
-			const String& prop,
-			const Color& c1, const Color& c2, float minv, float maxv)
+inline void color_by_10(GfxObj* go,
+                 const mol::EntityHandle& ev, 
+                 const String& prop,
+                 const Color& c1, const Color& c2)
 {
-  Gradient g;
-  g.SetColorAt(0.0,c1);
-  g.SetColorAt(1.0,c2);
-  go->ColorBy(mh,prop,g,minv, maxv);
+  go->ColorBy(ev,prop,c1,c2);
 }
-#endif
 
 }
 
 #define COLOR_BY_DEF_STD() \
-    .def("ColorBy",ost_gfx::color_by_e0)\
-    .def("ColorBy",ost_gfx::color_by_e1)\
-    .def("ColorBy",ost_gfx::color_by_e2)\
-    .def("ColorBy",ost_gfx::color_by_e3)\
-    .def("ColorBy",ost_gfx::color_by_e4)\
-    .def("ColorBy",ost_gfx::color_by_e5)\
-    .def("ColorBy",ost_gfx::color_by_e6)\
-    .def("ColorBy",ost_gfx::color_by_e7)
+    .def("ColorBy",ost_gfx::color_by_03)\
+    .def("ColorBy",ost_gfx::color_by_05)\
+    .def("ColorBy",ost_gfx::color_by_06)\
+    .def("ColorBy",ost_gfx::color_by_07)\
+    .def("ColorBy",ost_gfx::color_by_08)\
+    .def("ColorBy",ost_gfx::color_by_09)\
+    .def("ColorBy",ost_gfx::color_by_10)
 
 #if OST_IMG_ENABLED
 #  define COLOR_BY_DEF_MAP() \
-    .def("ColorBy",ost_gfx::color_by_m0)\
-    .def("ColorBy",ost_gfx::color_by_m1)\
-    .def("ColorBy",ost_gfx::color_by_m2)\
-    .def("ColorBy",ost_gfx::color_by_m3)
+    .def("ColorBy",ost_gfx::color_by_01)\
+    .def("ColorBy",ost_gfx::color_by_02)\
+    .def("ColorBy",ost_gfx::color_by_04)\
+    .def("ColorBy",ost_gfx::color_by_11)\
+    .def("ColorBy",ost_gfx::color_by_12)
 #else
 #  define COLOR_BY_DEF_MAP()
 #endif
diff --git a/modules/gfx/pymod/export_entity.cc b/modules/gfx/pymod/export_entity.cc
index 8d80170fb..23e341b04 100644
--- a/modules/gfx/pymod/export_entity.cc
+++ b/modules/gfx/pymod/export_entity.cc
@@ -92,16 +92,6 @@ void color_by_08(Entity* e,
   e->ColorBy(prop,c1,c2);
 }
 
-// temporary, see comment in gfx/entity.hh
-void detail_color_by_02(Entity* e,
-                        const String& prop, 
-                        const Gradient& gradient,
-                        float minv,float maxv)
-{
-  e->DetailColorBy(prop,gradient,minv,maxv);
-}
-
-
 void radius_by_01(Entity* e,
                   const String& prop, 
                   float rmin,float rmax,
@@ -255,7 +245,6 @@ void export_Entity()
     .add_property("selection", &Entity::GetSelection, 
                   &Entity::SetSelection)
     .def("GetView", &Entity::GetView)
-    .def("UpdateView", &Entity::UpdateView)
     .def("GetRenderModeName", &Entity::GetRenderModeName)
     .def("GetNotEmptyRenderModes", &Entity::GetNotEmptyRenderModes)
     .def("SetRenderMode", set_rm1, arg("keep")=false)
@@ -272,7 +261,6 @@ void export_Entity()
     .def("ColorBy", color_by_06)
     .def("ColorBy", color_by_07)
     .def("ColorBy", color_by_08)
-    .def("DetailColorBy", detail_color_by_02)
     COLOR_BY_DEF()
     .def("RadiusBy", radius_by_01)
     .def("RadiusBy", radius_by_02)
diff --git a/modules/gfx/pymod/export_gfx_obj.cc b/modules/gfx/pymod/export_gfx_obj.cc
index 3a0f4d7be..18e3454ee 100644
--- a/modules/gfx/pymod/export_gfx_obj.cc
+++ b/modules/gfx/pymod/export_gfx_obj.cc
@@ -25,77 +25,60 @@ using namespace ost::gfx;
 
 #include "color_by_def.hh"
 
-namespace {
-  // convenience for python
-  void set_mat_amb2(GfxObjBase* b, float c) {b->SetMatAmb(Color(c,c,c,1.0));}
-  void set_mat_diff2(GfxObjBase* b, float c) {b->SetMatDiff(Color(c,c,c,1.0));}
-  void set_mat_spec2(GfxObjBase* b, float c) {b->SetMatSpec(Color(c,c,c,1.0));}
-  void set_mat_emm2(GfxObjBase* b, float c) {b->SetMatEmm(Color(c,c,c,1.0));}
-  void set_mat1(GfxObjBase* b, float a, float d, float s, float p)
-  {
-    set_mat_amb2(b,a);
-    set_mat_diff2(b,d);
-    set_mat_spec2(b,s);
-    b->SetMatShin(p);
-    set_mat_emm2(b,0.0);
-  }
-  void set_mat2(GfxObjBase* b, Color a, Color d, Color s, float p)
-  {
-    b->SetMatAmb(a);
-    b->SetMatDiff(d);
-    b->SetMatSpec(s);
-    b->SetMatShin(p);
-    set_mat_emm2(b,0.0);
-  }
-}
-
 void export_GfxObj()
 {
-  class_<GfxObjBase, bases<GfxNode>, boost::noncopyable>("GfxObjBase",no_init)
-    .def("SetMatAmb",&GfxObjBase::SetMatAmb)
+  void (GfxObj::* set_mat_amb1)(const Color&) = &GfxObj::SetMatAmb;
+  void (GfxObj::* set_mat_amb2)(float) = &GfxObj::SetMatAmb;
+  void (GfxObj::* set_mat_diff1)(const Color&) = &GfxObj::SetMatDiff;
+  void (GfxObj::* set_mat_diff2)(float) = &GfxObj::SetMatDiff;
+  void (GfxObj::* set_mat_spec1)(const Color&) = &GfxObj::SetMatSpec;
+  void (GfxObj::* set_mat_spec2)(float) = &GfxObj::SetMatSpec;
+  void (GfxObj::* set_mat_emm1)(const Color&) = &GfxObj::SetMatEmm;
+  void (GfxObj::* set_mat_emm2)(float) = &GfxObj::SetMatEmm;
+  void (GfxObj::* set_mat1)(const Color&,const Color&, 
+                            const Color&, float) = &GfxObj::SetMat;
+  void (GfxObj::* set_mat2)(float,float,float,float) = &GfxObj::SetMat;
+
+  class_<GfxObj, bases<GfxNode>, boost::noncopyable>("GfxObj",no_init)
+    .def("GetCenter",&GfxObj::GetCenter)
+    .def("SetRenderMode", &GfxObj::SetRenderMode)
+    .def("GetRenderMode", &GfxObj::GetRenderMode)
+    .def("SetLineWidth", &GfxObj::SetLineWidth)
+    .def("GetLineWidth", &GfxObj::GetLineWidth)
+    .def("SetLineHalo",&GfxObj::SetLineHalo)
+    .def("GetLineHalo",&GfxObj::GetLineHalo)
+    .def("SetSphereDetail",&GfxObj::SetSphereDetail)
+    .def("SetArcDetail",&GfxObj::SetArcDetail)
+    .def("SetSplineDetail",&GfxObj::SetSplineDetail)
+    .def("SetMatAmb",set_mat_amb1)
     .def("SetMatAmb",set_mat_amb2)
-    .def("SetMatDiff",&GfxObjBase::SetMatDiff)
+    .def("SetMatDiff",set_mat_diff1)
     .def("SetMatDiff",set_mat_diff2)
-    .def("SetMatSpec",&GfxObjBase::SetMatSpec)
+    .def("GetTF", &GfxObj::GetTF, return_value_policy<copy_const_reference>())
+    .def("SetTF", &GfxObj::SetTF)
+    .def("SetMatSpec",set_mat_spec1)
     .def("SetMatSpec",set_mat_spec2)
-    .def("SetMatEmm",&GfxObjBase::SetMatEmm)
+    .def("SetMatEmm",set_mat_emm1)
     .def("SetMatEmm",set_mat_emm2)
-    .def("SetMatShin",&GfxObjBase::SetMatShin)
+    .def("SetMatShin",&GfxObj::SetMatShin)
     .def("SetMat",set_mat1)
     .def("SetMat",set_mat2)
-    .def("ContextSwitch", &GfxObjBase::ContextSwitch)
-    .def("SetRenderMode", &GfxObjBase::SetRenderMode)
-    .def("GetRenderMode", &GfxObjBase::GetRenderMode)
-    .def("GetCenter",&GfxObjBase::GetCenter)
-    .def("SetLineWidth", &GfxObjBase::SetLineWidth)
-    .def("SetPolyMode",&GfxObjBase::SetPolyMode)
-    .def("AALines",&GfxObjBase::AALines)
-    .def("SetLineHalo",&GfxObjBase::SetLineHalo)
-    .def("Outline",&GfxObjBase::Outline)
-    .def("SetOutlineMode",&GfxObjBase::SetOutlineMode)
-    .def("SetOutlineExpandFactor",&GfxObjBase::SetOutlineExpandFactor)
-    .def("SetOutlineExpandColor",&GfxObjBase::SetOutlineExpandColor)
-    .def("AmbientOcclusion",&GfxObjBase::AmbientOcclusion)
-    .def("SetAmbientLocalWeight",&GfxObjBase::SetAmbientLocalWeight)
-    .def("SetAmbientOcclusionWeight",&GfxObjBase::SetAmbientOcclusionWeight)
-    .def("SetOpacity",&GfxObjBase::SetOpacity)
-    .add_property("center", &GfxObjBase::GetCenter)
-    COLOR_BY_DEF()
-   ;
-
-  class_<GfxObj, bases<GfxObjBase>, boost::noncopyable>("GfxObj",no_init)
-    .def("GetTF", &GfxObj::GetTF, return_value_policy<copy_const_reference>())
-    .def("SetTF", &GfxObj::SetTF)
+    .def("SetPolyMode",&GfxObj::SetPolyMode)
+    .def("SetAALines",&GfxObj::SetAALines)
+    .def("SetOpacity",&GfxObj::SetOpacity)
+    .def("GetOpacity",&GfxObj::GetOpacity)
     .def("FlagRebuild",&GfxObj::FlagRebuild)
     .def("FlagRefresh",&GfxObj::FlagRefresh)
     .def("SetNormalSmoothFactor",&GfxObj::SetNormalSmoothFactor)
     .def("GetNormalSmoothFactor",&GfxObj::GetNormalSmoothFactor)
+    .def("SetOutlineMode",&GfxObj::SetOutlineMode)
+    .def("SetOutlineExpandFactor",&GfxObj::SetOutlineExpandFactor)
+    .def("SetOutlineExpandColor",&GfxObj::SetOutlineExpandColor)
     .def("SmoothVertices",&GfxObj::SmoothVertices)
+    .def("AmbientOcclusion",&GfxObj::AmbientOcclusion)
     .def("Debug",&GfxObj::Debug)
-    .def("GetAALines",&GfxObj::GetAALines)
-    .def("GetLineWidth",&GfxObj::GetLineWidth)
-    .def("GetLineHalo",&GfxObj::GetLineHalo)
-    .def("GetOpacity",&GfxObj::GetOpacity)
+    .add_property("center", &GfxObj::GetCenter)
+    COLOR_BY_DEF()
     ;
   register_ptr_to_python<GfxObjP>();
 
diff --git a/modules/gfx/pymod/export_render_options.cc b/modules/gfx/pymod/export_render_options.cc
index 51e9829c7..b27e55c46 100644
--- a/modules/gfx/pymod/export_render_options.cc
+++ b/modules/gfx/pymod/export_render_options.cc
@@ -102,8 +102,6 @@ void export_RenderOptions()
     .def("GetHelixEcc", &CartoonRenderOptions::GetHelixEcc)
     .def("SetHelixProfileType", &CartoonRenderOptions::SetHelixProfileType)
     .def("GetHelixProfileType", &CartoonRenderOptions::GetHelixProfileType)
-    .def("SetHelixMode", &CartoonRenderOptions::SetHelixMode)
-    .def("GetHelixMode", &CartoonRenderOptions::GetHelixMode)
     .def("SetStrandWidth", &CartoonRenderOptions::SetStrandWidth)
     .def("GetStrandWidth", &CartoonRenderOptions::GetStrandWidth)
     .def("SetStrandThickness", &CartoonRenderOptions::SetStrandThickness)
@@ -112,8 +110,6 @@ void export_RenderOptions()
     .def("GetStrandEcc", &CartoonRenderOptions::GetStrandEcc)
     .def("SetStrandProfileType", &CartoonRenderOptions::SetStrandProfileType)
     .def("GetStrandProfileType", &CartoonRenderOptions::GetStrandProfileType)
-    .def("SetStrandMode", &CartoonRenderOptions::SetStrandMode)
-    .def("GetStrandMode", &CartoonRenderOptions::GetStrandMode)
   ;
   
   class_<TraceRenderOptions, boost::shared_ptr<TraceRenderOptions>, bases<RenderOptions>, boost::noncopyable>("TraceRenderOptions")
@@ -123,8 +119,6 @@ void export_RenderOptions()
     .def("GetNormalSmoothFactor", &TraceRenderOptions::GetNormalSmoothFactor)
     .def("SetTubeRadius", &TraceRenderOptions::SetTubeRadius)
     .def("GetTubeRadius", &TraceRenderOptions::GetTubeRadius)
-    .def("SetRadius", &TraceRenderOptions::SetTubeRadius)
-    .def("GetRadius", &TraceRenderOptions::GetTubeRadius)
   ;
 }
 
diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc
index d87d76308..9cae54473 100644
--- a/modules/gfx/pymod/export_scene.cc
+++ b/modules/gfx/pymod/export_scene.cc
@@ -33,6 +33,7 @@ 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()
 {
@@ -48,13 +49,16 @@ GfxObjP scene_getitem(Scene* scene, const String& item)
   return scene->operator[](item);
 }
 
-} // anon ns
+}
 
+}
 
 void export_Scene()
 {
   def("Scene",get_scene,return_value_policy<reference_existing_object>());
 
+  def("set_offscreen_mode",&Scene::SetOffscreenMode);
+  
   // will be removed...
   def("PickAtom", &pick_atom);
 
@@ -87,9 +91,16 @@ 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)
@@ -117,36 +128,8 @@ void export_Scene()
     .def("SetShadow",&Scene::SetShadow)
     .def("SetShadowQuality",&Scene::SetShadowQuality)
     .def("AttachObserver",&Scene::AttachObserver)
-    .def("StartOffscreenMode",&Scene::StartOffscreenMode)
-    .def("StopOffscreenMode",&Scene::StopOffscreenMode)
-    .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)
-    .add_property("fog_near_offset",
-                  &Scene::GetFogNearOffset, 
-                  &Scene::SetFogNearOffset)
-    .add_property("fog_far_offset",
-                  &Scene::GetFogFarOffset, 
-                  &Scene::SetFogFarOffset)
-    
+    .def("__getitem__",scene_getitem)
   ;
 }
diff --git a/modules/gfx/pymod/glwin_base_proxy.hh b/modules/gfx/pymod/glwin_base_proxy.hh
index 8bfea675a..6c73fd142 100644
--- a/modules/gfx/pymod/glwin_base_proxy.hh
+++ b/modules/gfx/pymod/glwin_base_proxy.hh
@@ -26,9 +26,6 @@ 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/pymod/wrap_gfx.cc b/modules/gfx/pymod/wrap_gfx.cc
index 1c8ca0065..dd2049702 100644
--- a/modules/gfx/pymod/wrap_gfx.cc
+++ b/modules/gfx/pymod/wrap_gfx.cc
@@ -23,9 +23,7 @@ using namespace boost::python;
 #include <ost/gfx/prim_list.hh>
 #include <ost/gfx/gradient.hh>
 #include <ost/gfx/gfx_test_object.hh>
-#if OST_SHADER_SUPPORT_ENABLED
-#include <ost/gfx/shader.hh>
-#endif
+
 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
 
 extern void export_Scene();
@@ -172,15 +170,6 @@ BOOST_PYTHON_MODULE(_gfx)
 	.def("GetRel", &Stop::GetRel)
   ;
 
-#if OST_SHADER_SUPPORT_ENABLED
-  class_<Shader, boost::noncopyable>("Shader", no_init)
-    .def("Instance",&Shader::Instance,
-         return_value_policy<reference_existing_object>()).staticmethod("Instance")
-    .def("PushProgram",&Shader::PushProgram)
-    .def("PopProgram",&Shader::PopProgram)
-    .def("Activate",&Shader::Activate)
-    ;
-#endif
 
   export_primitives();
 }
diff --git a/modules/gfx/src/CMakeLists.txt b/modules/gfx/src/CMakeLists.txt
index 9f3d471ff..c07798109 100644
--- a/modules/gfx/src/CMakeLists.txt
+++ b/modules/gfx/src/CMakeLists.txt
@@ -10,7 +10,6 @@ gfx_fw.hh
 gfx_node.hh
 gfx_node_fw.hh
 gfx_node_visitor.hh
-gfx_object_base.hh
 gfx_object.hh
 gfx_object_fw.hh
 gfx_prim.hh
@@ -90,6 +89,7 @@ set(OST_GFX_SOURCES
 bitmap_io.cc
 color.cc
 primitives.cc
+offscreen_buffer.cc
 entity.cc
 
 symmetry_node.cc
@@ -173,21 +173,6 @@ 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 677b602c6..8de3d7ea0 100644
--- a/modules/gfx/src/bitmap_io.cc
+++ b/modules/gfx/src/bitmap_io.cc
@@ -38,8 +38,7 @@ 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) {
@@ -48,7 +47,6 @@ 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);
@@ -74,24 +72,20 @@ 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 25d63fd4a..f7b924c13 100644
--- a/modules/gfx/src/entity.cc
+++ b/modules/gfx/src/entity.cc
@@ -105,9 +105,8 @@ Entity::Entity(const String& name,
 
 impl::EntityRenderer* Entity::GetOrCreateRenderer(RenderMode::Type rm)
 {
-  RendererMap::iterator rit = renderer_.find(rm);
-  if(rit!=renderer_.end()) {
-    return rit->second;
+  if (renderer_.find(rm)!=renderer_.end()) {
+    return renderer_.find(rm)->second;
   }
   impl::EntityRenderer* r=NULL;
   switch (rm) {
@@ -118,22 +117,22 @@ impl::EntityRenderer* Entity::GetOrCreateRenderer(RenderMode::Type rm)
       r=new impl::CustomRenderer();
       break;
     case RenderMode::SLINE:
-      r=new impl::SlineRenderer(&trace_);
+      r=new impl::SlineRenderer(trace_);
       break;
     case RenderMode::LINE_TRACE:
-      r=new impl::LineTraceRenderer(&trace_);
+      r=new impl::LineTraceRenderer(trace_);
       break;
     case RenderMode::TRACE:
-      r=new impl::TraceRenderer(&trace_);
+      r=new impl::TraceRenderer(trace_);
       break;
     case RenderMode::HSC:
-      r=new impl::CartoonRenderer(&trace_,false);
+      r=new impl::CartoonRenderer(trace_);
       break;
     case RenderMode::CPK:
       r=new impl::CPKRenderer();
       break;
     case RenderMode::TUBE:
-      r=new impl::CartoonRenderer(&trace_, true);
+      r=new impl::CartoonRenderer(trace_, true);
       break;
     default:
       return 0;
@@ -145,14 +144,11 @@ impl::EntityRenderer* Entity::GetOrCreateRenderer(RenderMode::Type rm)
 void Entity::init(RenderMode::Type rm)
 {
   // TODO replace with def mat for this gfx obj type
-  SetMatAmb(Color(0,0,0));
-  SetMatDiff(Color(1,1,1));
-  SetMatSpec(Color(0.7,0.7,0.7));
-  SetMatShin(96);
+  SetMat(0.0,1.0,0.8,96.0);
 
   update_view_=true;
   render_mode_=rm;
-  trace_.ResetView(this->GetView());
+  trace_.SetView(this->GetView());
   sel_=this->GetView().CreateEmptyView();  
   impl::EntityRenderer* r=this->GetOrCreateRenderer(rm);
   if(!r) return;
@@ -201,18 +197,6 @@ void Entity::SetBlurFactors(float bf1,float bf2)
 void Entity::Rebuild()
 {
   geom::Vec3 delta=GetTF().GetTrans()-GetTF().GetCenter();
-
-  if(update_view_) {
-    EntityView nv=this->GetView();
-    for (RendererMap::iterator i=renderer_.begin(), 
-           e=renderer_.end(); i!=e; ++i) {
-      i->second->ClearViews();
-      i->second->AddView(nv);
-      i->second->UpdateViews();
-      i->second->PrepareRendering();
-    }
-  }
-
   this->ReapplyColorOps();
   FlagRebuild();
   geom::Vec3 center=this->GetCenter();
@@ -341,15 +325,16 @@ void Entity::CustomRenderGL(RenderPass pass)
        e=renderer_.end(); i!=e; ++i) {
     impl::EntityRenderer* r=i->second;
     if(r->IsEnabled()){
-      if(pass==STANDARD_RENDER_PASS || pass==OPAQUE_RENDER_PASS) {
-        r->Render(pass);
-        if(pass==STANDARD_RENDER_PASS && outline_flag_) {
-          r->VA().SetOutlineMode(outline_mode_);
+      switch(pass) {
+        case STANDARD_RENDER_PASS:
+        case OPAQUE_RENDER_PASS:
           r->Render(pass);
-          r->VA().SetOutlineMode(0);
-        }
-      } else if(pass==GLOW_RENDER_PASS && r->HasSelection()) {
-        r->Render(pass);
+          break;
+        case GLOW_RENDER_PASS:
+          if (r->HasSelection()) {
+            r->Render(pass);
+          }
+          break;
       }
     }
   }
@@ -780,16 +765,6 @@ void Entity::ColorBy(const String& prop,
   this->Apply(glop);
 }
 
-void Entity::DetailColorBy(const String& prop,
-                           const Gradient& gradient,
-                           float minv,float maxv,
-                           mol::Prop::Level level)
-{
-  GradientLevelColorOp glop = GradientLevelColorOp("",prop, gradient,minv,maxv,level);
-  glop.SetMask(DETAIL_COLOR);
-  this->Apply(glop);
-}
-
 void Entity::ColorBy(const String& prop,
                      const Color& c1, const Color& c2,
                      float minv, float maxv,
@@ -973,11 +948,4 @@ void Entity::ReapplyColorOps()
   GfxObj::ReapplyColorOps();
 }
 
-void Entity::UpdateView() 
-{
-  update_view_=true; 
-  Rebuild();
-  UpdatePositions();
-}
-
 }} // ns
diff --git a/modules/gfx/src/entity.hh b/modules/gfx/src/entity.hh
index c0b3c3a9f..368445df0 100644
--- a/modules/gfx/src/entity.hh
+++ b/modules/gfx/src/entity.hh
@@ -199,12 +199,6 @@ public:
                float minv,float maxv,
                mol::Prop::Level hint=mol::Prop::UNSPECIFIED);
 
-  // temporary, should be incorporated with ColorBy
-  void DetailColorBy(const String& prop, 
-                     const Gradient& gradient,
-                     float minv,float maxv,
-                     mol::Prop::Level hint=mol::Prop::UNSPECIFIED);
-
   // convenience
   void ColorBy(const String& prop, 
                const Gradient& gradient,
@@ -263,9 +257,6 @@ public:
   void ApplyOptions(RenderMode::Type render_mode,
                           RenderOptionsPtr& render_options);
   bool HasSelection() const;
-
-  void UpdateView();
-  
 protected:
 
   virtual void CustomPreRenderGL(bool flag);
diff --git a/modules/gfx/src/gfx_node.cc b/modules/gfx/src/gfx_node.cc
index 395658e96..f3a61c11e 100644
--- a/modules/gfx/src/gfx_node.cc
+++ b/modules/gfx/src/gfx_node.cc
@@ -160,11 +160,5 @@ 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 eb4fcc2bb..0f7ecc2d0 100644
--- a/modules/gfx/src/gfx_node.hh
+++ b/modules/gfx/src/gfx_node.hh
@@ -95,7 +95,6 @@ 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 4231be8dc..0a28a7e6e 100644
--- a/modules/gfx/src/gfx_object.cc
+++ b/modules/gfx/src/gfx_object.cc
@@ -41,7 +41,7 @@
 namespace ost { namespace gfx {
 
 GfxObj::GfxObj(const String& name):
-  GfxObjBase(name),
+  GfxNode(name),
   va_(),
   render_mode_(RenderMode::SIMPLE),
   debug_flags_(0),
@@ -49,6 +49,9 @@ GfxObj::GfxObj(const String& name):
   rebuild_(true),
   refresh_(false),
   line_width_(2.0),
+  sphere_detail_(4),
+  arc_detail_(4),
+  spline_detail_(8),
   poly_mode_(2),
   aalines_flag_(false),
   line_halo_(0.0),
@@ -57,22 +60,64 @@ GfxObj::GfxObj(const String& name):
   mat_update_(true),
   opacity_(1.0),
   smoothf_(0.0),
-  outline_flag_(false),
-  outline_mode_(1),
+  omode_(0),
   c_ops_(),
   labels_(),
   use_occlusion_(false)
 {
 }
 
-GfxObj::GfxObj(const GfxObj&):
-  GfxObjBase("") // to make the compiler happy
+GfxObj::~GfxObj()
+{}
+
+GfxObj::GfxObj(const GfxObj& o):
+  GfxNode("") // to make the compiler happy
 {}
 
 GfxObj& GfxObj::operator=(const GfxObj&) {return *this;}
 
-////////////////////////////////////////
-// the GfxNode interface
+void GfxObj::Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st)
+{
+  v.VisitObject(this,st);
+}
+
+int GfxObj::GetType() const
+{
+  return 1;
+}
+
+geom::AlignedCuboid GfxObj::GetBoundingBox() const
+{
+  return geom::AlignedCuboid(geom::Vec3(),geom::Vec3());
+}
+
+void GfxObj::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, 
+                           const mol::Transform& tf) const
+{
+  try {
+    geom::AlignedCuboid coord_limits=this->GetBoundingBox();
+    // update min/max by transforming all 8 corners of the bounding box and 
+    // comparing it against the current min/max
+    geom::Vec3 mmin=coord_limits.GetMin();
+    geom::Vec3 mmax=coord_limits.GetMax();
+    geom::Vec3 t1=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmin[2]));
+    geom::Vec3 t2=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmin[2]));
+    geom::Vec3 t3=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmin[2]));
+    geom::Vec3 t4=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmin[2]));
+    geom::Vec3 t5=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmax[2]));
+    geom::Vec3 t6=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmax[2]));
+    geom::Vec3 t7=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmax[2]));
+    geom::Vec3 t8=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmax[2]));
+    minc = geom::Min(minc, geom::Min(t1, geom::Min(t2, geom::Min(t3, 
+                     geom::Min(t4, geom::Min(t5, geom::Min(t6, 
+                     geom::Min(t7, t8))))))));
+    maxc = geom::Max(maxc, geom::Max(t1, geom::Max(t2, geom::Max(t3, 
+                     geom::Max(t4, geom::Max(t5, geom::Max(t6,
+                     geom::Max(t7, t8))))))));
+  } catch(Error& e) {
+    // in case the object is empty...
+  }
+}
 
 GfxNodeP GfxObj::Copy() const
 {
@@ -85,6 +130,9 @@ void GfxObj::DeepSwap(GfxObj& go)
   std::swap(transform_,go.transform_);
   std::swap(rebuild_,go.rebuild_);
   std::swap(refresh_,go.refresh_);
+  std::swap(sphere_detail_,go.sphere_detail_);
+  std::swap(arc_detail_,go.arc_detail_);
+  std::swap(spline_detail_,go.spline_detail_);
   std::swap(poly_mode_,go.poly_mode_);
   std::swap(aalines_flag_,go.aalines_flag_);
   std::swap(line_halo_,go.line_halo_);
@@ -93,132 +141,95 @@ void GfxObj::DeepSwap(GfxObj& go)
   std::swap(mat_update_,go.mat_update_);
   std::swap(opacity_,go.opacity_);
   std::swap(smoothf_,go.smoothf_);
-  std::swap(outline_flag_,go.outline_flag_);
-  std::swap(outline_mode_,go.outline_mode_);
-  std::swap(c_ops_,go.c_ops_);
-  std::swap(labels_,go.labels_);
-  std::swap(use_occlusion_,go.use_occlusion_);
-}
-
-void GfxObj::RenderGL(RenderPass pass)
-{
-  LOGN_TRACE("object " << GetName() << ": RenderGL()");
-
-  if(pass==0) {
-    if(mat_update_) {
-      LOGN_TRACE("updating material display list");
-      if(mat_dlist_==0) {
-        mat_dlist_=glGenLists(1);
-      }
-      glNewList(mat_dlist_,GL_COMPILE);
-      mat_.RenderGL();
-      glEndList();
-      mat_update_=false;
-    }
-    
-    if(rebuild_ || refresh_) {
-      PreRenderGL(rebuild_);
-      rebuild_=false;
-      refresh_=false;
-    }
-  }
-  if(IsVisible()) {
-    LOGN_TRACE("applying local transformation");
-    glMatrixMode(GL_MODELVIEW);
-    glPushMatrix();
-    glMultMatrix(transform_.GetTransposedMatrix().Data());
-    if(Scene::Instance().InOffscreenMode()) {
-      LOGN_TRACE("applying material");
-      mat_.RenderGL();
-    } else {
-      LOGN_TRACE("applying material display list");
-      glCallList(mat_dlist_);
-    }
-    LOGN_TRACE("calling custom render gl pass " << pass);
-
-    CustomRenderGL(pass);
-
-    if(pass==0 && outline_flag_>0) {
-      va_.SetOutlineMode(outline_mode_);
-      CustomRenderGL(pass);
-      va_.SetOutlineMode(0);
-    }
-
-    if(pass==1) {
-      LOGN_TRACE("drawing labels");
-      render_labels();
-    }
-
-    glPopMatrix();    
-  }
 }
 
+void GfxObj::CustomRenderGL(RenderPass pass) {}
+void GfxObj::CustomPreRenderGL(bool flag) {}
 
-void GfxObj::RenderPov(PovState& pov)
-{
-  if(IsVisible()) {
-    pov.start_obj(GetName(),1.0,1.0,1.0);
-    // apply local transformation
-    // using transform_
-    if(rebuild_ || refresh_) {
-      PreRenderGL(true);
-    }
-    CustomRenderPov(pov);
-    pov.end_obj();
-  }
-}
+void GfxObj::CustomRenderPov(PovState& pov) {}
 
-void GfxObj::Apply(GfxNodeVisitor& v, GfxNodeVisitor::Stack st)
+void GfxObj::RefreshVA(IndexedVertexArray& va)
 {
-  v.VisitObject(this,st);
+  va.SetLineWidth(GetLineWidth());
+  va.SetPolyMode(GetPolyMode());
+  va.SetAALines(GetAALines());
+  va.SetLineHalo(GetLineHalo());
+  va.DrawNormals(debug_flags_&0x1);
+  va.SetPolyMode(debug_flags_&0x2 ? 1 : 2);
+  va.UseAmbient(use_occlusion_);
+  va.FlagRefresh();
 }
 
-int GfxObj::GetType() const
+void GfxObj::OnInput(const InputEvent& e) 
 {
-  return 1;
-}
+  geom::Mat3 rot=gfx::Scene::Instance().GetTransform().GetRot();
+  geom::Vec3 cam_trans=gfx::Scene::Instance().GetTransform().GetTrans();  
+  float x=e.GetDelta()*M_PI/180.0;
+  bool transformed=false;
+  if (e.GetCommand()==INPUT_COMMAND_ROTX) {
+    transformed=true;
+    transform_.SetRot(AxisRotation(geom::Vec3(1,0,0)*rot,x)*transform_.GetRot());
+  } else if(e.GetCommand()==INPUT_COMMAND_ROTY) {
+    transformed=true;
+    transform_.SetRot(AxisRotation(geom::Vec3(0,1,0)*rot,x)*transform_.GetRot());
+  } else if(e.GetCommand()==INPUT_COMMAND_ROTZ) {
+    transformed=true;
+    transform_.SetRot(AxisRotation(geom::Vec3(0,0,1)*rot,x)*transform_.GetRot());
+  } else if(e.GetCommand()==INPUT_COMMAND_TRANSX ||
+            e.GetCommand()==INPUT_COMMAND_TRANSY) {
+ 
+    double mm[]={1,0,0,0,
+                 0,1,0,0,
+                 0,0,1,0,
+                 transform_.GetTrans()[0]-cam_trans[0],
+                 transform_.GetTrans()[1]-cam_trans[1],
+                 transform_.GetTrans()[2]-cam_trans[2], 1};
+    double pm[16];
+    glGetDoublev(GL_PROJECTION_MATRIX,pm);
+    GLint vp[4];
+    glGetIntegerv(GL_VIEWPORT,vp);
+    double wx,wy,wz;
+    gluProject(0.0,0.0,0.0,mm,pm,vp,&wx,&wy,&wz);
+    double ox,oy,oz;
+    gluUnProject(wx+1.0,wy+1.0,wz,mm,pm,vp,&ox,&oy,&oz);
 
-////////////////////////////////////////
-// now for the GfxObjBase interface
-void GfxObj::SetMatAmb(const Color& c)
-{
-  mat_.SetAmb(c);
-  mat_update_=true;
-  Scene::Instance().RequestRedraw();
+    float fx=ox;
+    float fy=oy;   
+    geom::Vec3 trans=transform_.GetTrans();
+    transformed=true;    
+    if (e.GetCommand()==INPUT_COMMAND_TRANSX) {
+      trans+=geom::Vec3(-fx*e.GetDelta(), 0.0, 0.0)*rot;
+    } else {
+      trans+=geom::Vec3(0.0, -fy*e.GetDelta(), 0.0)*rot;
+    }
+    transform_.SetTrans(trans);
+  }
+  if (transformed) {
+    GfxObjP obj=dyn_cast<GfxObj>(this->shared_from_this());
+    Scene::Instance().NodeTransformed(obj);
+  }
 }
 
-void GfxObj::SetMatDiff(const Color& c)
+const mol::Transform& GfxObj::GetTF() const
 {
-  mat_.SetDiff(c);
-  mat_update_=true;
-  Scene::Instance().RequestRedraw();
+  return transform_;
 }
 
-void GfxObj::SetMatSpec(const Color& c)
-{
-  mat_.SetSpec(c);
-  mat_update_=true;
-  Scene::Instance().RequestRedraw();
-}
 
-void GfxObj::SetMatShin(float s)
+void GfxObj::SetTF(const mol::Transform& tf)
 {
-  mat_.SetShin(s);
-  mat_update_=true;
-  Scene::Instance().RequestRedraw();
+  transform_=tf;
 }
 
-void GfxObj::SetMatEmm(const Color& c)
+geom::Vec3 GfxObj::GetCenter() const 
 {
-  mat_.SetEmm(c);
-  mat_update_=true;
-  Scene::Instance().RequestRedraw();
+  return this->GetBoundingBox().GetCenter();
 }
 
-void GfxObj::ContextSwitch()
+bool GfxObj::OnSelect(const geom::Line3& l, geom::Vec3& result, 
+                      float zlim, bool pick_flag)
 {
-  FlagRebuild();
-  GfxNode::ContextSwitch();
+  return false;
 }
 
 void GfxObj::SetRenderMode(RenderMode::Type m)
@@ -234,248 +245,197 @@ RenderMode::Type GfxObj::GetRenderMode() const
   return render_mode_;
 }
 
-geom::Vec3 GfxObj::GetCenter() const 
+void GfxObj::FlagRebuild()
 {
-  return this->GetBoundingBox().GetCenter();
+  rebuild_=true;
+  Scene::Instance().RequestRedraw();
 }
 
-void GfxObj::SetLineWidth(float w)
+void GfxObj::FlagRefresh()
 {
-  va_.SetLineWidth(w);
-  line_width_=std::max(float(0.01),w);
-  FlagRefresh();
-  Scene::Instance().RenderModeChanged(GetName());
+  refresh_=true;
+  Scene::Instance().RequestRedraw();
 }
 
-void GfxObj::SetPolyMode(unsigned int m)
+void GfxObj::SetNormalSmoothFactor(float smoothf)
 {
-  if(m==poly_mode_) return;
-  poly_mode_=std::min((unsigned int)2,m);
-  va_.SetPolyMode(poly_mode_);
-  FlagRefresh();
+  smoothf_=smoothf;
+  FlagRebuild();
 }
 
-void GfxObj::AALines(bool f)
+float GfxObj::GetNormalSmoothFactor() const
 {
-  if(f==aalines_flag_) return;
-  va_.SetAALines(f);
-  aalines_flag_=f;
-  FlagRefresh();
+  return smoothf_;
 }
 
-void GfxObj::SetLineHalo(float f)
+void GfxObj::OnRenderModeChange()
 {
-  va_.SetLineHalo(f);
-  line_halo_=f;
-  FlagRefresh();
+  Scene::Instance().ObjectChanged(GetName());
+  Scene::Instance().RenderModeChanged(GetName());
 }
 
-void GfxObj::Outline(bool f)
+void GfxObj::SetLineWidth(float w)
 {
-  outline_flag_=f;
+  line_width_=std::max(float(0.01),w);
   FlagRefresh();
-  if(f) {
-    outline_mode_=std::min(3,std::max(1,outline_mode_));
-  }
-  Scene::Instance().RequestRedraw();
-}
-
-void GfxObj::SetOutlineMode(int m)
-{
-  outline_mode_=m;
-  if(outline_flag_) {
-    FlagRefresh();
-    Scene::Instance().RequestRedraw();
-  }
+  Scene::Instance().RenderModeChanged(GetName());
 }
 
-void GfxObj::SetOutlineExpandFactor(float f)
+float GfxObj::GetLineWidth() const
 {
-  va_.SetOutlineExpandFactor(f);
+  return line_width_;
 }
 
-void GfxObj::SetOutlineExpandColor(const Color& c)
+void GfxObj::SetSphereDetail(unsigned int d)
 {
-  va_.SetOutlineExpandColor(c);
-}
-
-void GfxObj::AmbientOcclusion(bool f)
-{
-  va_.UseAmbient(f);
-  Scene::Instance().RequestRedraw();
-}
-
-void GfxObj::SetAmbientLocalWeight(float w)
-{
-  va_.AmbientLocalWeight(w);
-  Scene::Instance().RequestRedraw();
+  if(d==sphere_detail_) return;
+  sphere_detail_=d;
+  FlagRebuild();
 }
 
-void GfxObj::SetAmbientOcclusionWeight(float w)
+unsigned int GfxObj::GetSphereDetail() const
 {
-  va_.AmbientOcclusionWeight(w);
-  Scene::Instance().RequestRedraw();
+  return sphere_detail_;
 }
 
-void GfxObj::SetOpacity(float o)
+void GfxObj::SetArcDetail(unsigned int d)
 {
-  opacity_=o;
+  if(d==arc_detail_) return;
+  arc_detail_=d;
   FlagRebuild();
 }
 
-void GfxObj::ColorBy(const mol::EntityView& ev, 
-                      const String& prop,
-                      const Gradient& g, float minv, float maxv)
+unsigned int GfxObj::GetArcDetail() const
 {
-  LOGN_VERBOSE("ColorBy not implemented for this gfx object");
+  return arc_detail_;
 }
 
-#if OST_IMG_ENABLED
-void GfxObj::ColorBy(const img::MapHandle& mh,
-                      const String& prop,
-                      const Gradient& g, float minv, float maxv)
+void GfxObj::SetSplineDetail(unsigned int d)
 {
-  LOGN_VERBOSE("ColorBy not implemented for this gfx object");
-}
-#endif
-
-//////////////////////////////////////////////////
-// and now for the rest of the GfxObj interface
-
-geom::AlignedCuboid GfxObj::GetBoundingBox() const
-{
-  return geom::AlignedCuboid(geom::Vec3(),geom::Vec3());
+  if(d==spline_detail_) return;
+  spline_detail_=d;
+  FlagRebuild();
 }
 
-void GfxObj::ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, 
-                           const mol::Transform& tf) const
+unsigned int GfxObj::GetSplineDetail() const
 {
-  try {
-    geom::AlignedCuboid coord_limits=this->GetBoundingBox();
-    // update min/max by transforming all 8 corners of the bounding box and 
-    // comparing it against the current min/max
-    geom::Vec3 mmin=coord_limits.GetMin();
-    geom::Vec3 mmax=coord_limits.GetMax();
-    geom::Vec3 t1=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmin[2]));
-    geom::Vec3 t2=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmin[2]));
-    geom::Vec3 t3=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmin[2]));
-    geom::Vec3 t4=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmin[2]));
-    geom::Vec3 t5=tf.Apply(geom::Vec3(mmin[0], mmin[1], mmax[2]));
-    geom::Vec3 t6=tf.Apply(geom::Vec3(mmin[0], mmax[1], mmax[2]));
-    geom::Vec3 t7=tf.Apply(geom::Vec3(mmax[0], mmax[1], mmax[2]));
-    geom::Vec3 t8=tf.Apply(geom::Vec3(mmax[0], mmin[1], mmax[2]));
-    minc = geom::Min(minc, geom::Min(t1, geom::Min(t2, geom::Min(t3, 
-                     geom::Min(t4, geom::Min(t5, geom::Min(t6, 
-                     geom::Min(t7, t8))))))));
-    maxc = geom::Max(maxc, geom::Max(t1, geom::Max(t2, geom::Max(t3, 
-                     geom::Max(t4, geom::Max(t5, geom::Max(t6,
-                     geom::Max(t7, t8))))))));
-  } catch(Error& e) {
-    // in case the object is empty...
-  }
+  return spline_detail_;
 }
 
-
-void GfxObj::CustomRenderGL(RenderPass pass) {}
-
-void GfxObj::CustomPreRenderGL(bool flag) {}
-
-void GfxObj::CustomRenderPov(PovState& pov) {}
-
-bool GfxObj::OnSelect(const geom::Line3& l, geom::Vec3& result, 
-                      float zlim, bool pick_flag)
+void GfxObj::SetPolyMode(unsigned int m)
 {
-  return false;
+  if(m==poly_mode_) return;
+  poly_mode_=std::min((unsigned int)2,m);
+  FlagRefresh();
 }
 
-void GfxObj::OnInput(const InputEvent& e) 
+unsigned int GfxObj::GetPolyMode() const
 {
-  geom::Mat3 rot=gfx::Scene::Instance().GetTransform().GetRot();
-  geom::Vec3 cam_trans=gfx::Scene::Instance().GetTransform().GetTrans();  
-  float x=e.GetDelta()*M_PI/180.0;
-  bool transformed=false;
-  if (e.GetCommand()==INPUT_COMMAND_ROTX) {
-    transformed=true;
-    transform_.SetRot(AxisRotation(geom::Vec3(1,0,0)*rot,x)*transform_.GetRot());
-  } else if(e.GetCommand()==INPUT_COMMAND_ROTY) {
-    transformed=true;
-    transform_.SetRot(AxisRotation(geom::Vec3(0,1,0)*rot,x)*transform_.GetRot());
-  } else if(e.GetCommand()==INPUT_COMMAND_ROTZ) {
-    transformed=true;
-    transform_.SetRot(AxisRotation(geom::Vec3(0,0,1)*rot,x)*transform_.GetRot());
-  } else if(e.GetCommand()==INPUT_COMMAND_TRANSX ||
-            e.GetCommand()==INPUT_COMMAND_TRANSY) {
- 
-    double mm[]={1,0,0,0,
-                 0,1,0,0,
-                 0,0,1,0,
-                 transform_.GetTrans()[0]-cam_trans[0],
-                 transform_.GetTrans()[1]-cam_trans[1],
-                 transform_.GetTrans()[2]-cam_trans[2], 1};
-    double pm[16];
-    glGetDoublev(GL_PROJECTION_MATRIX,pm);
-    GLint vp[4];
-    glGetIntegerv(GL_VIEWPORT,vp);
-    double wx,wy,wz;
-    gluProject(0.0,0.0,0.0,mm,pm,vp,&wx,&wy,&wz);
-    double ox,oy,oz;
-    gluUnProject(wx+1.0,wy+1.0,wz,mm,pm,vp,&ox,&oy,&oz);
+  return poly_mode_;
+}
 
-    float fx=ox;
-    float fy=oy;   
-    geom::Vec3 trans=transform_.GetTrans();
-    transformed=true;    
-    if (e.GetCommand()==INPUT_COMMAND_TRANSX) {
-      trans+=geom::Vec3(-fx*e.GetDelta(), 0.0, 0.0)*rot;
-    } else {
-      trans+=geom::Vec3(0.0, -fy*e.GetDelta(), 0.0)*rot;
-    }
-    transform_.SetTrans(trans);
-  }
-  if (transformed) {
-    GfxObjP obj=dyn_cast<GfxObj>(this->shared_from_this());
-    Scene::Instance().NodeTransformed(obj);
-  }
+void GfxObj::SetAALines(bool f)
+{
+  if(f==aalines_flag_) return;
+  aalines_flag_=f;
+  FlagRefresh();
 }
 
-const mol::Transform& GfxObj::GetTF() const
+bool GfxObj::GetAALines() const
 {
-  return transform_;
+  return aalines_flag_;
 }
 
+void GfxObj::SetLineHalo(float f)
+{
+  line_halo_=f;
+  FlagRefresh();
+}
 
-void GfxObj::SetTF(const mol::Transform& tf)
+float GfxObj::GetLineHalo() const
 {
-  transform_=tf;
+  return line_halo_;
 }
 
-void GfxObj::FlagRebuild()
+void GfxObj::SetOutlineMode(int m)
 {
-  rebuild_=true;
-  Scene::Instance().RequestRedraw();
+  omode_=m;
+  FlagRefresh();
 }
 
-void GfxObj::FlagRefresh()
+void GfxObj::SetOutlineExpandFactor(float f)
 {
-  refresh_=true;
-  Scene::Instance().RequestRedraw();
+  va_.SetOutlineExpandFactor(f);
 }
 
-void GfxObj::SetNormalSmoothFactor(float smoothf)
+void GfxObj::SetOutlineExpandColor(const Color& c)
 {
-  smoothf_=smoothf;
-  FlagRebuild();
+  va_.SetOutlineExpandColor(c);
 }
 
-float GfxObj::GetNormalSmoothFactor() const
+void GfxObj::RenderGL(RenderPass pass)
 {
-  return smoothf_;
+  LOGN_TRACE("object " << GetName() << ": RenderGL()");
+
+  if(pass==0) {
+    if(mat_update_) {
+      LOGN_TRACE("updating material display list");
+      if(mat_dlist_==0) {
+        mat_dlist_=glGenLists(1);
+      }
+      glNewList(mat_dlist_,GL_COMPILE);
+      mat_.RenderGL();
+      glEndList();
+      mat_update_=false;
+    }
+    
+    if(rebuild_ || refresh_) {
+      PreRenderGL(rebuild_);
+      rebuild_=false;
+      refresh_=false;
+    }
+  }
+  if(IsVisible()) {
+    LOGN_TRACE("applying local transformation");
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glMultMatrix(transform_.GetTransposedMatrix().Data());
+    if(Scene::Instance().InOffscreenMode()) {
+      LOGN_TRACE("applying material");
+      mat_.RenderGL();
+    } else {
+      LOGN_TRACE("applying material display list");
+      glCallList(mat_dlist_);
+    }
+    LOGN_TRACE("calling custom render gl pass " << pass);
+
+    CustomRenderGL(pass);
+
+    if(pass==0 && omode_>0) {
+      va_.SetOutlineMode(omode_);
+      CustomRenderGL(pass);
+      va_.SetOutlineMode(0);
+    }
+
+    if(pass==1) {
+      LOGN_TRACE("drawing labels");
+      render_labels();
+    }
+
+    glPopMatrix();    
+  }
 }
 
-void GfxObj::OnRenderModeChange()
+
+void GfxObj::RenderPov(PovState& pov)
 {
-  Scene::Instance().ObjectChanged(GetName());
-  Scene::Instance().RenderModeChanged(GetName());
+  if(IsVisible()) {
+    pov.start_obj(GetName(),1.0,1.0,1.0);
+    // apply local transformation
+    // using transform_
+    CustomRenderPov(pov);
+    pov.end_obj();
+  }
 }
 
 void GfxObj::PreRenderGL(bool f)
@@ -486,7 +446,6 @@ void GfxObj::PreRenderGL(bool f)
 
 void GfxObj::Clear()
 {
-  va_.Clear();
 }
 
 Color GfxObj::Ele2Color(const String& ele)
@@ -528,6 +487,90 @@ void GfxObj::ClearLabels()
   labels_.clear();
 }
 
+void GfxObj::SetMatAmb(const Color& c)
+{
+  mat_.SetAmb(c);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMatAmb(float c)
+{
+  mat_.SetAmb(c);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMatDiff(const Color& c)
+{
+  mat_.SetDiff(c);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMatDiff(float c)
+{
+  mat_.SetDiff(c);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMatSpec(const Color& c)
+{
+  mat_.SetSpec(c);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMatSpec(float c)
+{
+  mat_.SetSpec(c);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMatShin(float s)
+{
+  mat_.SetShin(s);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMatEmm(const Color& c)
+{
+  mat_.SetEmm(c);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMatEmm(float c)
+{
+  mat_.SetEmm(c);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMat(const Color& amb, const Color& diff, const Color& spec, float shin)
+{
+  SetMatAmb(amb);
+  SetMatDiff(diff);
+  SetMatSpec(spec);
+  SetMatShin(shin);
+  SetMatEmm(0.0);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::SetMat(float amb, float diff, float spec, float shin)
+{
+  SetMatAmb(amb);
+  SetMatDiff(diff);
+  SetMatSpec(spec);
+  SetMatShin(shin);
+  SetMatEmm(0.0);
+  mat_update_=true;
+  Scene::Instance().RequestRedraw();
+}
 
 Material GfxObj::GetMaterial() const
 {
@@ -551,12 +594,139 @@ void GfxObj::GLCleanup()
 void GfxObj::OnGLCleanup()
 {}
 
+void GfxObj::SetOpacity(float o)
+{
+  opacity_=o;
+  FlagRebuild();
+}
+
+float GfxObj::GetOpacity() const
+{
+  return opacity_;
+}
+
 void GfxObj::SmoothVertices(float smoothf)
 {
   va_.SmoothVertices(smoothf);
   FlagRefresh();
 }
 
+void GfxObj::AmbientOcclusion(bool f)
+{
+  use_occlusion_=f;
+  va_.UseAmbient(f);
+  Scene::Instance().RequestRedraw();
+}
+
+void GfxObj::ColorBy(const mol::EntityView& ev, 
+                      const String& prop,
+                      const Gradient& g, float minv, float maxv)
+{
+  LOGN_VERBOSE("ColorBy not implemented for this gfx object");
+}
+
+
+void GfxObj::ColorBy(const mol::EntityView& ev, 
+                      const String& prop,
+                      const Color& c1, const Color& c2, float minv, float maxv)
+{
+  Gradient g;
+  g.SetColorAt(0.0,c1);
+  g.SetColorAt(1.0,c2);
+  this->ColorBy(ev,prop,g,minv,maxv);
+}
+
+#if OST_IMG_ENABLED
+void GfxObj::ColorBy(const img::MapHandle& mh,
+                      const String& prop,
+                      const Gradient& g, float minv, float maxv)
+{
+  LOGN_VERBOSE("ColorBy not implemented for this gfx object");
+}
+
+void GfxObj::ColorBy(const img::MapHandle& mh,
+                      const String& prop,
+                      const Color& c1, const Color& c2, float minv, float maxv)
+{
+  Gradient g;
+  g.SetColorAt(0.0,c1);
+  g.SetColorAt(1.0,c2);
+  this->ColorBy(mh,prop,g,minv,maxv);
+}
+
+void GfxObj::ColorBy(const img::MapHandle& mh,
+                      const String& prop,
+                      const Gradient& g)
+{
+  ost::img::alg::Stat stat;
+  mh.Apply(stat);
+  float min = static_cast<float>(stat.GetMinimum());
+  float max = static_cast<float>(stat.GetMaximum());
+  std::pair<float,float> minmax = std::make_pair(min,max);
+  this->ColorBy(mh,prop,g,minmax.first, minmax.second);
+}
+
+void GfxObj::ColorBy(const img::MapHandle& mh,
+                      const String& prop,
+                      const Color& c1, const Color& c2)
+{
+  ost::img::alg::Stat stat;
+  mh.Apply(stat);
+  float min = static_cast<float>(stat.GetMinimum());
+  float max = static_cast<float>(stat.GetMaximum());
+  std::pair<float,float> minmax = std::make_pair(min,max);
+  this->ColorBy(mh,prop,c1,c2,minmax.first, minmax.second);
+}
+
+#endif //OST_IMG_ENABLED
+
+void GfxObj::ColorBy(const mol::EntityHandle& eh, 
+                      const String& prop,
+                      const Gradient& g, float minv, float maxv)
+{
+  this->ColorBy(eh.CreateFullView(),prop,g,minv,maxv);
+}
+    
+void GfxObj::ColorBy(const mol::EntityHandle& eh, 
+                      const String& prop,
+                      const Color& c1, const Color& c2, float minv, float maxv)
+{
+  Gradient g;
+  g.SetColorAt(0.0,c1);
+  g.SetColorAt(1.0,c2);
+  this->ColorBy(eh,prop,g,minv,maxv);
+}
+
+void GfxObj::ColorBy(const mol::EntityView& ev, 
+                      const String& prop,
+                      const Gradient& g)
+{
+  std::pair<float,float> minmax = ev.GetMinMax(prop);
+  this->ColorBy(ev,prop,g,minmax.first, minmax.second);
+}
+    
+void GfxObj::ColorBy(const mol::EntityView& ev, 
+                      const String& prop,
+                      const Color& c1, const Color& c2)
+{
+  std::pair<float,float> minmax = ev.GetMinMax(prop);
+  this->ColorBy(ev,prop,c1,c2,minmax.first, minmax.second);
+}
+
+void GfxObj::ColorBy(const mol::EntityHandle& eh, 
+                      const String& prop,
+                      const Gradient& g)
+{
+  this->ColorBy(eh.CreateFullView(),prop,g);
+}
+
+void GfxObj::ColorBy(const mol::EntityHandle& eh, 
+                      const String& prop,
+                      const Color& c1, const Color& c2)
+{
+  this->ColorBy(eh.CreateFullView(),prop,c1,c2);
+}
+
 namespace {
 
 float normalize(float v, float min_v, float max_v)
@@ -591,9 +761,4 @@ void GfxObj::CleanColorOps(){
   c_ops_.release();
 }
 
-void GfxObj::Debug(unsigned int flags)
-{
-  va_.DrawNormals(flags & 0x1);
-}
-
 }} // ns
diff --git a/modules/gfx/src/gfx_object.hh b/modules/gfx/src/gfx_object.hh
index 0b9322542..5a4bd4877 100644
--- a/modules/gfx/src/gfx_object.hh
+++ b/modules/gfx/src/gfx_object.hh
@@ -33,67 +33,58 @@
 #include <ost/config.hh>
 #include <ost/gfx/module_config.hh>
 
+#include <ost/gfx/color_ops/color_op.hh>
+
+#include <ost/geom/geom.hh>
+#include <ost/mol/entity_handle.hh>
+#include <ost/mol/entity_view.hh>
 #include <ost/mol/transform.hh>
 
+
+#if OST_IMG_ENABLED
+#  include <ost/img/map.hh>
+#endif
+
 #include "gfx_object_fw.hh"
-#include "gfx_object_base.hh"
+#include "gfx_node.hh"
 #include "gfx_prim.hh"
 #include "vertex_array.hh"
 #include "input.hh"
+#include "render_mode.hh"
+#include "material.hh"
+#include "gradient.hh"
+
 
 namespace ost { namespace gfx {
 
 class Scene; // fw decl
 
-/// \brief main class for all graphic objects
-class DLLEXPORT_OST_GFX GfxObj: public GfxObjBase
+/// \brief Base class for all graphical rendering objects
+class DLLEXPORT_OST_GFX GfxObj: public GfxNode
 {
+
 public:
   GfxObj(const String& name);
+  virtual ~GfxObj();
 
-  // gfx node interface
   virtual GfxNodeP Copy() const;
-  virtual void DeepSwap(GfxObj& go);
-  virtual void RenderGL(RenderPass pass);
-  virtual void RenderPov(PovState& pov);
+
   virtual void Apply(GfxNodeVisitor& v,GfxNodeVisitor::Stack st);
+
   virtual int GetType() const;
-  //
-
-  // gfx obj base interface
-  virtual void SetMatAmb(const Color& c);
-  virtual void SetMatDiff(const Color& c);
-  virtual void SetMatSpec(const Color& c);
-  virtual void SetMatShin(float s);
-  virtual void SetMatEmm(const Color& c);
-  virtual void ContextSwitch();
-  virtual void SetRenderMode(RenderMode::Type m);
-  virtual RenderMode::Type GetRenderMode() const;
-  virtual geom::Vec3 GetCenter() const;
-  virtual void SetLineWidth(float w);
-  virtual void SetPolyMode(unsigned int m);
-  virtual void AALines(bool f);
-  virtual void SetLineHalo(float f);
-  virtual void Outline(bool f);
-  virtual void SetOutlineMode(int m);
-  virtual void SetOutlineExpandFactor(float f);
-  virtual void SetOutlineExpandColor(const Color& c);
-  virtual void AmbientOcclusion(bool f);
-  virtual void SetAmbientLocalWeight(float w);
-  virtual void SetAmbientOcclusionWeight(float w);
-  virtual void SetOpacity(float f);
-  virtual void ColorBy(const mol::EntityView& ev, 
-                       const String& prop,
-                       const Gradient& g, float minv, float maxv);
-#if OST_IMG_ENABLED
-  virtual void ColorBy(const img::MapHandle& mh,
-                       const String& prop,
-                       const Gradient& g,float minv, float maxv);
-#endif
 
-  // end of gfx obj base interface
+  virtual void RenderGL(RenderPass pass);
+
+  virtual void RenderPov(PovState& pov);
 
-  // new gfx obj virtual interface starts here
+  void Clear();
+  
+  /// \brief get transform
+  const mol::Transform& GetTF() const;
+  /// \brief set transform
+  void SetTF(const mol::Transform& tf);
+  
+  virtual geom::Vec3 GetCenter() const;
 
   /// \brief returns the left-bottom-front and the right-top-back corner
   /// that encompasses all graphical elements in this object
@@ -107,10 +98,8 @@ public:
   virtual void ProcessLimits(geom::Vec3& minc, geom::Vec3& maxc, 
                              const mol::Transform& tf) const;
 
-  // implemented in derived classes for the actual GL rendering
   virtual void CustomRenderGL(RenderPass pass);
 
-  // implemented in derived classes for the actual POVray export
   virtual void CustomRenderPov(PovState& pov);
 
   // handle pick (select) event
@@ -127,20 +116,43 @@ public:
 
   // input event entry point
   virtual void OnInput(const InputEvent& e);
-
-  // informs derived class that render mode has changes
+  
+  virtual void DeepSwap(GfxObj& go);
+  
   virtual void OnRenderModeChange();
   virtual void OnGLCleanup();
-  //
 
-  /// \brief removes all graphical elements
-  void Clear();
-  
-  /// \brief get transform
-  const mol::Transform& GetTF() const;
-  /// \brief set transform
-  void SetTF(const mol::Transform& tf);
+  /// \brief change render mode
+  virtual void SetRenderMode(RenderMode::Type m);
+  /// \brief current render mode
+  RenderMode::Type GetRenderMode() const;
+
+  /// \brief set line width
+  void SetLineWidth(float w);
   
+  /// \brief get line width 
+  float GetLineWidth() const;
+
+  void SetSphereDetail(unsigned int d);
+  unsigned int GetSphereDetail() const;
+
+  // subdivions per 90deg
+  void SetArcDetail(unsigned int d);
+  unsigned int GetArcDetail() const;
+
+  void SetSplineDetail(unsigned int d);
+  unsigned int GetSplineDetail() const;
+
+  void SetPolyMode(unsigned int m);
+  unsigned int GetPolyMode() const;
+
+  // sophisticated line anti-aliasing, requires shader
+  void SetAALines(bool f);
+  bool GetAALines() const;
+
+  void SetLineHalo(float f);
+  float GetLineHalo() const;
+
   // add a label at the given position
   void AddLabel(const String& s, const geom::Vec3& pos, const Color& col, float psize);
   // convenience method
@@ -149,38 +161,112 @@ public:
   void AddLabel(const String& s, const geom::Vec3& pos, float psize);
   // convenience method
   void AddLabel(const String& s, const geom::Vec3& pos);
+
   // remove all labels
   void ClearLabels();
 
+  void SetMatAmb(const Color& c);
+  void SetMatAmb(float c);
+  void SetMatDiff(const Color& c);
+  void SetMatDiff(float c);
+  void SetMatSpec(const Color& c);
+  void SetMatSpec(float c);
+  void SetMatShin(float s);
+  void SetMatEmm(const Color& c);
+  void SetMatEmm(float c);
+  void SetMat(const Color& amb, const Color& diff, const Color& spec, float shin);
+  void SetMat(float amb, float diff, float spec, float shin);
+
+  void SetOpacity(float o);
+  float GetOpacity() const;
+
+  static Color Ele2Color(const String& ele);
+
   void FlagRebuild();
   void FlagRefresh();
 
-  bool GetAALines() const {return aalines_flag_;}
-  float GetLineWidth() const {return line_width_;}
-  float GetLineHalo() const {return line_halo_;}
-  float GetOpacity() const {return opacity_;}
-
   void SetNormalSmoothFactor(float smoothf);
   float GetNormalSmoothFactor() const;
 
   Material GetMaterial() const;
   void SetMaterial(const Material& m);
 
+  void SetOutlineMode(int m);
+  void SetOutlineExpandFactor(float f);
+  void SetOutlineExpandColor(const Color& c);
+
   // experimental, don't use
   void SmoothVertices(float smoothf);
+  // experimental, don't use
+  void AmbientOcclusion(bool f);
  
   void GLCleanup();
 
-  // this really should not be here
-  static Color Ele2Color(const String& ele);
+  /// \brief color each component based on the gradient-mapped property of 
+  ///    the given entity
+  virtual void ColorBy(const mol::EntityView& ev, 
+                       const String& prop,
+                       const Gradient& g, float minv, float maxv);
+    
+  /// \brief convenience method
+  void ColorBy(const mol::EntityView& ev, 
+               const String& prop,
+               const Color& c1, const Color& c2, float minv, float maxv);
+
+  /// \brief convenience method
+  void ColorBy(const mol::EntityHandle& eh, 
+               const String& prop,
+               const Gradient& g, float minv, float maxv);
+  /// \brief convenience method
+  void ColorBy(const mol::EntityHandle& eh, 
+               const String& prop,
+               const Color& c1, const Color& c2, float minv, float maxv);
+  // convenience method
+  void ColorBy(const mol::EntityView& ev, 
+               const String& prop,
+               const Gradient& g);
+  // convenience method
+  void ColorBy(const mol::EntityView& ev, 
+               const String& prop,
+               const Color& c1, const Color& c2);
+  // convenience method
+  void ColorBy(const mol::EntityHandle& ev, 
+               const String& prop,
+               const Gradient& g);
+  // convenience method
+  void ColorBy(const mol::EntityHandle& ev, 
+               const String& prop,
+               const Color& c1, const Color& c2);
+#if OST_IMG_ENABLED
+  // convenience method
+  void ColorBy(const img::MapHandle& mh,
+               const String& prop,
+               const Gradient& g);
+  // convenience method
+  void ColorBy(const img::MapHandle& mh,
+               const String& prop,
+               const Color& c1, const Color& c2);
+  // dito for maps
+  virtual void ColorBy(const img::MapHandle& mh,
+                       const String& prop,
+                       const Gradient& g,float minv, float maxv);
+  // convenience method
+  void ColorBy(const img::MapHandle& mh,
+               const String& prop,
+               const Color& c1, const Color& c2, float minv, float maxv);  
+#endif
 
-  void Debug(unsigned int flags);
+  void Debug(unsigned int flags) {debug_flags_=flags; RefreshVA();}
 
  protected:
   
   void PreRenderGL(bool flag);
   virtual void CustomPreRenderGL(bool flag);
 
+  void RefreshVA(IndexedVertexArray& va);
+
+  virtual void RefreshVA() {RefreshVA(va_);}
+  
  private:
   GfxObj(const GfxObj& o);
   GfxObj& operator=(const GfxObj&);
@@ -189,16 +275,19 @@ public:
   void AppendColorOp(gfx::ColorOp* op);
   void CleanColorOps();
   void ReapplyColorOps();
-  void render_labels() const;
 
   IndexedVertexArray va_;
   RenderMode::Type render_mode_;
   unsigned int debug_flags_;
  
+ private: 
   mol::Transform transform_;
   bool rebuild_;
   bool refresh_;
   float line_width_;
+  unsigned int sphere_detail_;
+  unsigned int arc_detail_;
+  unsigned int spline_detail_;
   unsigned int poly_mode_;
   bool aalines_flag_;
   float line_halo_;
@@ -209,12 +298,12 @@ public:
 
   float opacity_;
   float smoothf_;
-  bool outline_flag_;
-  int outline_mode_;
+  int omode_;
 
   boost::ptr_vector<gfx::ColorOp> c_ops_;
 
   TextPrimList labels_;
+  void render_labels() const;
 
   bool use_occlusion_;
 };
diff --git a/modules/gfx/src/gfx_prim.hh b/modules/gfx/src/gfx_prim.hh
index aead54653..1ec2bc25a 100644
--- a/modules/gfx/src/gfx_prim.hh
+++ b/modules/gfx/src/gfx_prim.hh
@@ -48,19 +48,13 @@ typedef std::vector<SpherePrim> SpherePrimList;
 
 struct CylinderPrim {
   CylinderPrim():
-    start(),end(),radius(1.0),color1(),color2(),length(1.0),rotmat(),rotmat_t()
+    start(),end(),radius(1.0),color(),length(1.0),rotmat(),rotmat_t()
   {
     calc_rotmat();
   }
 
   CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float rad, const Color& col):
-    start(st),end(en),radius(rad),color1(col),color2(col),length(geom::Length(end-start)),rotmat(),rotmat_t() 
-  {
-    calc_rotmat();
-  }
-
-  CylinderPrim(const geom::Vec3& st, const geom::Vec3& en, float rad, const Color& col1, const Color& col2):
-    start(st),end(en),radius(rad),color1(col1),color2(col2),length(geom::Length(end-start)),rotmat(),rotmat_t() 
+    start(st),end(en),radius(rad),color(col),length(geom::Length(end-start)),rotmat(),rotmat_t() 
   {
     calc_rotmat();
   }
@@ -69,7 +63,7 @@ struct CylinderPrim {
 
   geom::Vec3 start,end;
   float radius;
-  Color color1, color2;
+  Color color;
   float length;
   geom::Mat3 rotmat;
   geom::Mat3 rotmat_t;
diff --git a/modules/gfx/src/glwin_base.hh b/modules/gfx/src/glwin_base.hh
index 996ed2ba1..69ce40525 100644
--- a/modules/gfx/src/glwin_base.hh
+++ b/modules/gfx/src/glwin_base.hh
@@ -33,15 +33,11 @@ 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/backbone_trace.cc b/modules/gfx/src/impl/backbone_trace.cc
index fb4b714cc..c61fd23a5 100644
--- a/modules/gfx/src/impl/backbone_trace.cc
+++ b/modules/gfx/src/impl/backbone_trace.cc
@@ -39,7 +39,7 @@ public:
   {
     if(last_chain_ && chain!=last_chain_) {
       if(!list_.empty()) {
-        backbone_trace_->AddNodeEntryList(list_);
+        backbone_trace_->AddNodeList(list_);
         list_.clear();
       }
       last_chain_=chain;
@@ -51,15 +51,15 @@ public:
   {
     if(!mol::InSequence(last_residue_,res)) {
       if(!list_.empty()) {
-        backbone_trace_->AddNodeEntryList(list_);
+        backbone_trace_->AddNodeList(list_);
         list_.clear();
       }
     }
     // determine atom to add to list
     mol::AtomHandle ca = res.GetCentralAtom();
     if (ca) {
-      NodeEntry entry={ca, GfxObj::Ele2Color(ca.GetAtomProps().element),
-                       GfxObj::Ele2Color(ca.GetAtomProps().element),
+      NodeEntry entry={ca, GfxObj::Ele2Color(ca.GetElement()),
+                       GfxObj::Ele2Color(ca.GetElement()),
                        geom::Vec3(0.0,0.0,0.0), // this will be set by the gfx trace obj
                        res.GetCentralNormal(),
                        1.0,
@@ -76,7 +76,7 @@ public:
   virtual void OnExit()
   {
     if (!list_.empty()) {
-      backbone_trace_->AddNodeEntryList(list_);
+      backbone_trace_->AddNodeList(list_);
       list_.clear();
     }
   }
@@ -87,19 +87,95 @@ private:
   NodeEntryList      list_;
 };
 
-BackboneTrace::BackboneTrace()
-{}
-
 BackboneTrace::BackboneTrace(const mol::EntityView& ent)
 {
   view_=ent;
-  Rebuild();
+  TraceBuilder trace(this);
+  if (view_) {
+    view_.Apply(trace);
+  }
 }
 
-void BackboneTrace::ResetView(const mol::EntityView& ent)
+BackboneTrace::BackboneTrace()
+{
+  
+}
+
+void BackboneTrace::SetView(const mol::EntityView& ent)
 {
   view_=ent;
-  Rebuild();
+  if (view_) {
+    node_list_list_.clear();
+    TraceBuilder trace(this);    
+    view_.Apply(trace);
+  }
+}
+
+void BackboneTrace::AddNodeList(const NodeEntryList& l)
+{
+  if(l.size()>=3) {
+    node_list_list_.push_back(l);
+    // assign direction and normal vectors for each entry
+    // they are composed of the i-1 -> i and i->i+1 directions
+    //
+    // this same algorithm is used in the spline generation, so
+    // perhaps all of this here is not necessary ?!
+    //
+    NodeEntry* e0=&node_list_list_.back()[0];
+    NodeEntry* e1=&node_list_list_.back()[1];
+    NodeEntry* e2=&node_list_list_.back()[2];
+    geom::Vec3 p0 = e0->atom.GetPos();
+    geom::Vec3 p1 = e1->atom.GetPos();
+    geom::Vec3 p2 = e2->atom.GetPos();
+
+    e0->direction=geom::Normalize(p1-p0);
+    // e0->normal is set afterwards to normal of second one
+    // backup residue normal
+    e0->v1 = e0->normal;
+
+    //reference normal to avoid twisting
+    geom::Vec3 nref=geom::Normalize(geom::Cross(p0-p1,p2-p1));
+
+    // start loop with the second
+    unsigned int i=1;
+    for(;i<node_list_list_.back().size()-1;++i) {
+      geom::Vec3 p10 = p0-p1;
+      geom::Vec3 p12 = p2-p1;
+      if(p10==-p12 || p10==p12) p12+=geom::Vec3(0.001,0.001,0.001);
+      e1->v1=e1->normal;
+      // twist avoidance
+      if(geom::Dot(e0->v1,e1->v1)<0.0) {
+        e1->v1=-e1->v1;
+      }
+      e1->normal=geom::Normalize(geom::Cross(p10,p12));
+      float omega=0.5*acos(geom::Dot(geom::Normalize(p10),geom::Normalize(p12)));
+      geom::Vec3 orth=geom::AxisRotation(e1->normal, -omega)*p12;
+      e1->direction=geom::Normalize(geom::Cross(e1->normal,orth));
+
+      // align normals to avoid twisting
+      //if(geom::Dot(e1->normal,nref)<0.0) e1->normal=-e1->normal;
+      //nref=e1->normal;
+      // skip over shift for the last iteration
+      if(i==node_list_list_.back().size()-2) break;
+      // shift to i+1 for next iteration
+      e0=&node_list_list_.back()[i];
+      e1=&node_list_list_.back()[i+1];
+      e2=&node_list_list_.back()[i+2];
+      p0 = e0->atom.GetPos();
+      p1 = e1->atom.GetPos();
+      p2 = e2->atom.GetPos();
+    }
+    // finish remaining values
+    // i is at size-2 due to break statement above
+    node_list_list_.back()[0].normal=node_list_list_.back()[1].normal;
+    node_list_list_.back()[i+1].direction=geom::Normalize(p2-p1);
+    node_list_list_.back()[i+1].v1=node_list_list_.back()[i+1].normal;
+    if (geom::Dot(node_list_list_.back()[i].v1,
+                  node_list_list_.back()[i+1].v1)<0.0) {
+      node_list_list_.back()[i+1].v1=-node_list_list_.back()[i+1].v1;
+    }
+    node_list_list_.back()[i+1].normal=node_list_list_.back()[i].normal;
+  }
 }
 
 int BackboneTrace::GetListCount() const
@@ -119,104 +195,97 @@ NodeEntryList& BackboneTrace::GetList(int index)
 
 void BackboneTrace::Rebuild()
 {
-  if (view_) {
-    node_list_list_.clear();
-    TraceBuilder trace(this);    
-    view_.Apply(trace);
-  }
+  TraceBuilder trace(this);
+  view_.Apply(trace);  
 }
 
-void BackboneTrace::AddNodeEntryList(const NodeEntryList& l)
+NodeListSubset::NodeListSubset(BackboneTrace& trace, int index):
+  trace_(trace), list_index_(index), at_start_(0), at_end_(0)
 {
-  if(l.size()>=3) {
-    node_list_list_.push_back(l);
-    PrepList(node_list_list_.back());
-  }
 }
 
-void BackboneTrace::PrepList(NodeEntryList& nelist)
-{
-  // assign direction and normal vectors for each entry
-  // they are composed of the i-1 -> i and i->i+1 directions
-  //
-  // this same algorithm is used in the spline generation, so
-  // perhaps all of this here is not necessary ?!
-  //
-  NodeEntry* e0=&nelist[0];
-  NodeEntry* e1=&nelist[1];
-  NodeEntry* e2=&nelist[2];
-  geom::Vec3 p0 = e0->atom.GetPos();
-  geom::Vec3 p1 = e1->atom.GetPos();
-  geom::Vec3 p2 = e2->atom.GetPos();
-  
-  e0->direction=geom::Normalize(p1-p0);
-  // e0->normal is set afterwards to normal of second one
-  // backup residue normal
-  e0->v1 = e0->normal;
-  
-  //reference normal to avoid twisting
-  geom::Vec3 nref=geom::Normalize(geom::Cross(p0-p1,p2-p1));
+TraceSubset::TraceSubset(BackboneTrace& trace, 
+                         const mol::EntityView& view, int n):
+  trace_(trace), overshoot_(n)
+{
+  this->Update(view);
+}
+
+TraceSubset::TraceSubset(BackboneTrace& trace, int n):
+  trace_(trace), overshoot_(n)
+{
   
-  // start loop with the second
-  unsigned int i=1;
-  for(;i<nelist.size()-1;++i) {
-    geom::Vec3 p10 = p0-p1;
-    geom::Vec3 p12 = p2-p1;
-    if(p10==-p12 || p10==p12) p12+=geom::Vec3(0.001,0.001,0.001);
-    e1->v1=e1->normal;
-    // twist avoidance
-    if(geom::Dot(e0->v1,e1->v1)<0.0) {
-      e1->v1=-e1->v1;
+}
+
+
+void TraceSubset::NodeListEnd(NodeListSubset& nl, int c, int s)
+{
+  if (nl.GetSize()>0) {
+    int n=std::min(s-(nl.indices_.back()+1), overshoot_);
+    nl.at_end_=n;    
+    while (n>0) {
+      nl.indices_.push_back(nl.indices_.back()+1);
+      --n;
     }
-    e1->normal=geom::Normalize(geom::Cross(p10,p12));
-    float omega=0.5*acos(geom::Dot(geom::Normalize(p10),geom::Normalize(p12)));
-    geom::Vec3 orth=geom::AxisRotation(e1->normal, -omega)*p12;
-    e1->direction=geom::Normalize(geom::Cross(e1->normal,orth));
-    
-    // align normals to avoid twisting
-    //if(geom::Dot(e1->normal,nref)<0.0) e1->normal=-e1->normal;
-    //nref=e1->normal;
-    // skip over shift for the last iteration
-    if(i==nelist.size()-2) break;
-    // shift to i+1 for next iteration
-    e0=&nelist[i];
-    e1=&nelist[i+1];
-    e2=&nelist[i+2];
-    p0 = e0->atom.GetPos();
-    p1 = e1->atom.GetPos();
-    p2 = e2->atom.GetPos();
   }
-  // finish remaining values
-  // i is at size-2 due to break statement above
-  nelist[0].normal=nelist[1].normal;
-  nelist[i+1].direction=geom::Normalize(p2-p1);
-  nelist[i+1].v1=nelist[i+1].normal;
-  if (geom::Dot(nelist[i].v1,
-                nelist[i+1].v1)<0.0) {
-    nelist[i+1].v1=-nelist[i+1].v1;
+}
+
+void TraceSubset::NodeListStart(NodeListSubset& nl, int c)
+{
+  if (nl.GetSize()==0 && c>0) {
+    for (int i=std::max(0,c-overshoot_); i<c; ++i) {
+      nl.indices_.push_back(i);
+    }
+    nl.at_start_=nl.indices_.size();
   }
-  nelist[i+1].normal=nelist[i].normal;
 }
 
-BackboneTrace BackboneTrace::CreateSubset(const mol::EntityView& subview)
+
+void TraceSubset::Update(const mol::EntityView& view)
 {
-  BackboneTrace nrvo;
-  nrvo.view_=subview;
-  nrvo.node_list_list_.clear();
-  for(NodeEntryListList::const_iterator nitnit=node_list_list_.begin();nitnit!=node_list_list_.end();++nitnit) {
-    NodeEntryList new_nlist;
-    const NodeEntryList& nlist=*nitnit;
-    for(NodeEntryList::const_iterator nit=nlist.begin();nit!=nlist.end();++nit) {
-      if(subview.FindAtom(nit->atom).IsValid()) {
-	new_nlist.push_back(*nit);
+
+  lists_.clear();
+  if (!view.IsValid()) {
+    return;
+  }
+  for (int i=0; i<trace_.GetListCount(); ++i) {
+    const NodeEntryList& l=trace_.GetList(i); 
+    int c=0;
+    NodeEntryList::const_iterator j=l.begin(),e=l.end();  
+    NodeListSubset curr(trace_, i);
+    while (j!=e) {  
+      while (j!=e && view.FindAtom(j->atom)) {
+        if (curr.indices_.empty()) {
+          this->NodeListStart(curr, c);
+        }
+        curr.indices_.push_back(c);
+        ++j; ++c;
+      }
+      if (curr.GetSize()) {
+        this->NodeListEnd(curr, curr.indices_.back(), l.size());
+        lists_.push_back(curr);
+        curr=NodeListSubset(trace_, i);
+      } else {
+        ++c; ++j;        
       }
-    }
-    if(!new_nlist.empty()) {
-      nrvo.node_list_list_.push_back(new_nlist);
     }
   }
-  return nrvo;
 }
 
-}}} // ns
+NodeListSubset& NodeListSubset::operator=(const NodeListSubset& rhs)
+{
+  trace_=rhs.trace_;
+  list_index_=rhs.list_index_;
+  indices_=rhs.indices_;
+  return *this;
+}
+
+TraceSubset& TraceSubset::operator=(const TraceSubset& rhs)
+{
+  trace_=rhs.trace_;
+  lists_=rhs.lists_;
+  overshoot_=rhs.overshoot_;
+  return *this;
+}
 
+}}}
diff --git a/modules/gfx/src/impl/backbone_trace.hh b/modules/gfx/src/impl/backbone_trace.hh
index debcc54b5..c6663f12c 100644
--- a/modules/gfx/src/impl/backbone_trace.hh
+++ b/modules/gfx/src/impl/backbone_trace.hh
@@ -40,41 +40,99 @@ class BackboneTraceBuilder;
 class DLLEXPORT_OST_GFX BackboneTrace {
 public:
 
-  // empty trace
-  BackboneTrace();
-
-  // initialize with a view, and build
   BackboneTrace(const mol::EntityView& ent);
-
-  // number of node-lists
+  BackboneTrace();
+  
   int GetListCount() const;
-
-  // grab a list
+  
   const NodeEntryList& GetList(int index) const;
-  // grab a list
   NodeEntryList& GetList(int index);
-
-  // reset the view and rebuild
-  void ResetView(const mol::EntityView& ent);
-
-  // used internally - adds a finished nodelist
-  void AddNodeEntryList(const NodeEntryList& entries);  
   
-  // used internally - calculates some derived values for a nodelist
-  static void PrepList(NodeEntryList& nelist);
-
-  // re-creates internal nodelist-list based on view
-  void Rebuild();
+  void SetView(const mol::EntityView& ent);
+  
+  // used internally
+  void AddNodeList(const NodeEntryList& entries);  
   
-  // extract portions of this backbone trace for a subview
-  // this is faster then re-generating a trace
-  BackboneTrace CreateSubset(const mol::EntityView& subview);
+  void Rebuild();
   
 private:  
   mol::EntityView      view_;
   NodeEntryListList    node_list_list_;
 };
 
+/// \internal
+/// \brief a subset of a node list
+class DLLEXPORT_OST_GFX NodeListSubset {
+public:
+  friend class TraceSubset;
+  
+  NodeListSubset(BackboneTrace& trace, int index);
+  
+  int GetSize() const 
+  {
+     return indices_.size();
+  }
+  int AtStart() const 
+  { 
+    return at_start_;
+  }
+  
+  int AtEnd() const 
+  { 
+    return at_end_;
+  }  
+  const NodeEntry& operator [](int index) const 
+  {
+    assert(index>=0 && index<static_cast<int>(indices_.size()));    
+    return trace_.GetList(list_index_)[indices_[index]];
+  }
+  NodeEntry& operator [](int index)
+  {
+    assert(index>=0 && index<static_cast<int>(indices_.size()));    
+    return trace_.GetList(list_index_)[indices_[index]];
+  }  
+  NodeListSubset& operator=(const NodeListSubset& rhs);    
+private:
+  BackboneTrace&    trace_;
+  int               list_index_;
+protected:
+  std::vector<int>  indices_;
+  int               at_start_;
+  int               at_end_;
+};
+
+/// \brief a subset of the trace
+class DLLEXPORT_OST_GFX TraceSubset {
+public:
+  TraceSubset(BackboneTrace& trace, const mol::EntityView& view, int n);
+  TraceSubset(BackboneTrace& trace, int n);
+  
+  const NodeListSubset& operator[](int index) const
+  {
+    return lists_[index];
+  }
+  
+  NodeListSubset& operator[](int index)
+  {
+    return lists_[index];
+  }
+  
+  int GetSize() const
+  {
+    return lists_.size();
+  }
+  void SetOvershoot(int n) { overshoot_=n; }
+  int GetOvershoot() const { return overshoot_; }
+  TraceSubset& operator=(const TraceSubset& rhs);  
+  void Update(const mol::EntityView& view);
+private:
+  void NodeListStart(NodeListSubset& nl, int c);
+  void NodeListEnd(NodeListSubset& nl, int c, int s);
+  BackboneTrace& trace_;
+  std::vector<NodeListSubset> lists_;
+  int overshoot_;
+};
+
 }}}
 
 #endif
diff --git a/modules/gfx/src/impl/cartoon_renderer.cc b/modules/gfx/src/impl/cartoon_renderer.cc
index f4a52b7ee..08f0a0c3e 100644
--- a/modules/gfx/src/impl/cartoon_renderer.cc
+++ b/modules/gfx/src/impl/cartoon_renderer.cc
@@ -16,17 +16,8 @@
 // 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 "cartoon_renderer.hh"
 
-#include <Eigen/Core>
-#include <Eigen/Array>
-#include <Eigen/SVD>
-#include <Eigen/LU>
 
 #include <ost/gfx/entity.hh>
 #include <ost/gfx/impl/tabulated_trig.hh>
@@ -39,11 +30,16 @@ static const unsigned int MAX_ARC_DETAIL=12;
 
 using namespace impl;
 
-CartoonRenderer::CartoonRenderer(BackboneTrace* trace, bool force_tube): 
+CartoonRenderer::CartoonRenderer(BackboneTrace& trace, bool force_tube): 
   TraceRendererBase(trace, 3),   force_tube_(force_tube),
   options_(new CartoonRenderOptions(force_tube))
 {
-  this->SetName(force_tube ? "Smooth Tube" : "Helix & Strand Cartoon");
+if(force_tube){
+  this->SetName("Smooth Tube");
+}
+else{
+  this->SetName("Helix & Strand Cartoon");
+}
 }
 
 void CartoonRenderer::SetForceTube(bool force_tube)
@@ -51,14 +47,13 @@ void CartoonRenderer::SetForceTube(bool force_tube)
   force_tube_ = force_tube;
 }
 
-void CartoonRenderer::PrepareRendering(const BackboneTrace& subset, 
+void CartoonRenderer::PrepareRendering(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);
@@ -66,43 +61,45 @@ void CartoonRenderer::PrepareRendering(const BackboneTrace& subset,
     va.SetColorMaterial(true);
     va.SetMode(0x4);
     va.SetPolyMode(options_->GetPolyMode());
-    for (int node_list=0; node_list<subset.GetListCount(); ++node_list) {
+    spline_list_list.clear();
+    for (int node_list=0; node_list<subset.GetSize(); ++node_list) {
       // first build the spline
-      SplineEntryList spl;
-      const NodeEntryList& nl=subset.GetList(node_list);
-      for (unsigned int i=0; i<nl.size();++i) {
+      Spline spl;
+      const NodeListSubset& nl=subset[node_list];
+      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()) {
             type=1;
           } else if(sst.IsExtended()) {
-            type=2;
+            if(!sst2.IsExtended()) {
+              type=3; // end of strand
+            } else {
+              type=2;
+            }
           }
         }
-        SplineEntry ee(entry.atom.GetPos(),entry.direction,
-                       entry.normal, entry.rad, 
-                       is_sel ? sel_clr : entry.color1, 
-                       is_sel ? sel_clr : entry.color2, type);
+        SplineEntry& ee = spl.AddEntry(entry.atom.GetPos(),entry.direction,
+                                       entry.normal, entry.rad, 
+                                       is_sel ? sel_clr : entry.color1, 
+                                       is_sel ? sel_clr : entry.color2, type);
         ee.v1 = entry.v1;
-        spl.push_back(ee);
-      }
-      if(!spl.empty()) {
-        tmp_sll.push_back(spl);
       }
+      spline_list_list.push_back(spl.Generate(spline_detail));
+      // now create the shape around the interpolated pathway
     }
-    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());
+    RebuildSplineObj(spline_list_list.back(), va, spline_list_list, subset, is_sel);    
+    va.SmoothNormals(options_->GetNormalSmoothFactor());
   }  
 }
-
 void CartoonRenderer::PrepareRendering()
 {
   TraceRendererBase::PrepareRendering();
@@ -117,6 +114,8 @@ void CartoonRenderer::PrepareRendering()
   state_=0;
 }
 
+void CartoonRenderer::Render(){}
+
 bool CartoonRenderer::CanSetOptions(RenderOptionsPtr& render_options)
 {
  return render_options.get()->GetRenderMode()==RenderMode::HSC;
@@ -132,258 +131,95 @@ 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,
-                                       const SplineEntryListList& spline_list_list,
-                                       bool is_sel)
+void CartoonRenderer::RebuildSplineObj(const SplineEntryList& l, 
+                                       IndexedVertexArray& va,
+                                       SplineEntryListList& spline_list_list,
+                                       const TraceSubset& subset, bool is_sel)
 {
   unsigned int detail = std::min(MAX_ARC_DETAIL,
                                  std::max(options_->GetArcDetail(),
                                  (unsigned int)1));
+  int spline_detail=std::max((unsigned int) 1, options_->GetSplineDetail());
   std::vector<TraceProfile> profiles;
   float factor=is_sel ? 0.2 : 0.0;
   profiles.push_back(GetCircProfile(detail,
 				    options_->GetTubeRadius()*options_->GetTubeRatio()+factor,
 				    options_->GetTubeRadius()+factor, 
 				    options_->GetTubeProfileType(),
-				    1.0)); // profile 0 = tube
+				    1.0)); // tube
   if (!force_tube_) {
     profiles.push_back(GetCircProfile(detail,
 				      options_->GetHelixWidth()+factor,
 				      options_->GetHelixThickness()+factor,
 				      options_->GetHelixProfileType(),
-				      options_->GetHelixEcc())); // profile 1 = helix
+				      options_->GetHelixEcc())); // helix
     profiles.push_back(GetCircProfile(detail,
 				      options_->GetStrandWidth()+factor,
 				      options_->GetStrandThickness()+factor,
 				      options_->GetStrandProfileType(),
-				      options_->GetStrandEcc())); // profile 2 = strand
-    profiles.push_back(profiles.back()); // profile 3==2, strand
-
+				      options_->GetStrandEcc())); // strand
     profiles.push_back(GetCircProfile(detail,
-				      1.7*options_->GetStrandWidth()+factor,
-				      1.1*options_->GetStrandThickness()+factor,
-				      options_->GetStrandProfileType(),
-				      options_->GetStrandEcc())); // profile 4 = arrow start
+				      0.1*options_->GetStrandWidth()+factor,
+				      options_->GetStrandThickness()+factor,
+				      options_->GetTubeProfileType(),
+				      1.0)); // arrow end, tube profile
     profiles.push_back(GetCircProfile(detail,
-				      0.01*options_->GetStrandWidth()+factor,
+				      1.7*options_->GetStrandWidth()+factor,
 				      1.1*options_->GetStrandThickness()+factor,
 				      options_->GetStrandProfileType(),
-				      options_->GetStrandEcc())); // profile 5 = arrow end
-
+				      options_->GetStrandEcc())); // arrow start
   }
 
   // iterate over all spline segments
-  for(SplineEntryListList::const_iterator it=spline_list_list.begin();
+  for(SplineEntryListList::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;
-    if(slist.empty()) continue;
-    TraceProfile tprof1=TransformAndAddProfile(profiles,slist[0],va);
-    CapProfile(tprof1,slist[0],true,va);
+    SplineEntryList& slist=*it;
+    const NodeListSubset& nl=subset[it-spline_list_list.begin()];
+    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;
+    }
+    TraceProfile tprof1=TransformAndAddProfile(profiles,slist[sit],va);
+    CapProfile(tprof1,slist[sit],true,va);
     TraceProfile tprof2;
-    unsigned int sc=1;
-    for (; sc<slist.size(); ++sc) {
-      if(slist.at(sc).type==3) {
-        if(slist.at(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.at(sc));
-          se.type1=4;
-          if(options_->GetStrandMode()==1) se.type2=5;
-          tprof2=TransformAndAddProfile(profiles,se, va);
-        }
+    SplineEntry& last_se=slist[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;
+        tprof2=TransformAndAddProfile(profiles,slist[sc], va);
+        last_se=slist[sc];
       } 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.at(sc-1),false,va);
+    CapProfile(tprof1,slist[send-1],false,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 d8a98f761..ff9097e5c 100644
--- a/modules/gfx/src/impl/cartoon_renderer.hh
+++ b/modules/gfx/src/impl/cartoon_renderer.hh
@@ -16,11 +16,6 @@
 // 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
-*/
-
 #ifndef OST_GFX_CARTOON_RENDERER_HH
 #define OST_GFX_CARTOON_RENDERER_HH
 
@@ -39,26 +34,25 @@ namespace ost { namespace gfx { namespace impl {
 /// \internal
 class DLLEXPORT_OST_GFX CartoonRenderer: public TraceRendererBase {
 public:
-  CartoonRenderer(BackboneTrace* trace, bool force_tube=false);
-  virtual ~CartoonRenderer();
+  CartoonRenderer(BackboneTrace& trace, bool force_tube=false);
 
   virtual void PrepareRendering();
+  virtual void Render();
 
   virtual bool CanSetOptions(RenderOptionsPtr& render_options);
   virtual void SetOptions(RenderOptionsPtr& render_options);
   virtual RenderOptionsPtr GetOptions();
 
+
   virtual void SetForceTube(bool force_tube);
-  
-private:
-  void PrepareRendering(const BackboneTrace& subset, IndexedVertexArray& va, 
-                        SplineEntryListList& spline_list_list, bool is_sel);
 
-  void FudgeSplineObj(IndexedVertexArray&, SplineEntryListList&);
 
-  void RebuildSplineObj(IndexedVertexArray& va,
-                        const SplineEntryListList& spline_list_list,
-                        bool is_sel);
+  virtual ~CartoonRenderer();
+  
+private:
+  void RebuildSplineObj(const SplineEntryList& l, IndexedVertexArray& va,
+                        SplineEntryListList& spline_list_list,
+                        const TraceSubset& subset, bool is_sel);
   
   void CapProfile(const impl::TraceProfile& p, 
                   const impl::SplineEntry& se, 
@@ -72,6 +66,9 @@ 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/debug_renderer.cc b/modules/gfx/src/impl/debug_renderer.cc
index c77dca568..918117400 100644
--- a/modules/gfx/src/impl/debug_renderer.cc
+++ b/modules/gfx/src/impl/debug_renderer.cc
@@ -33,7 +33,7 @@ namespace gfx {
 using namespace impl;
 using namespace mol;
 
-DebugRenderer::DebugRenderer(BackboneTrace* trace): 
+DebugRenderer::DebugRenderer(BackboneTrace& trace): 
   TraceRendererBase(trace, 2), options_(new SlineRenderOptions()) {
   this->SetName("Debug");
 }
@@ -51,7 +51,7 @@ void DebugRenderer::PrepareRendering()
 
   for(NodeEntryListList::const_iterator ll_it=node_list_list_->begin();ll_it!=node_list_list_->end();++ll_it) {
 
-    SplineEntryList spl;
+    Spline spl;
     for(NodeEntryList::const_iterator it=(*ll_it).begin();it!=(*ll_it).end();++it) {
       int type=0;
       ResidueHandle resh = it->atom.GetResidue();
@@ -62,13 +62,12 @@ void DebugRenderer::PrepareRendering()
         type=2;
       }
 
-      SplineEntry ee(it->atom.GetPos(),it->direction,it->normal,
-                     it->rad,it->color1,it->color2,type);
+      SplineEntry& ee = spl.AddEntry(it->atom.GetPos(),it->direction,it->normal,
+                                     it->rad,it->color1,it->color2,type);
       ee.v1 = it->v1;
-      spl.push_back(ee);
     }
 
-    SplineEntryList sel = Spline::Generate(spl,std::max((unsigned int) 1,options_->GetSplineDetail()));
+    SplineEntryList sel = spl.Generate(std::max((unsigned int) 1,options_->GetSplineDetail()));
 
     SplineEntryList::const_iterator sit = sel.begin();
     geom::Vec3 ap = sit->position;
diff --git a/modules/gfx/src/impl/debug_renderer.hh b/modules/gfx/src/impl/debug_renderer.hh
index 3a2b6e79a..206f592dd 100644
--- a/modules/gfx/src/impl/debug_renderer.hh
+++ b/modules/gfx/src/impl/debug_renderer.hh
@@ -30,7 +30,7 @@ namespace ost { namespace gfx { namespace impl {
 
 class DLLEXPORT_OST_GFX DebugRenderer: public TraceRendererBase {
 public:
-  DebugRenderer(BackboneTrace* trace);
+  DebugRenderer(BackboneTrace& trace);
 
   virtual void PrepareRendering();
   virtual void Render();
diff --git a/modules/gfx/src/impl/entity_detail.cc b/modules/gfx/src/impl/entity_detail.cc
index 4d2857b4b..ccc160078 100644
--- a/modules/gfx/src/impl/entity_detail.cc
+++ b/modules/gfx/src/impl/entity_detail.cc
@@ -87,41 +87,85 @@ void GfxView::AddBond(const BondHandle& b)
 }
 
 
+void SplineEntry::ToQuat()
+{
+  // assert orthonormal system
+  // TODO: this seems broken
+  geom::Vec3 dir = geom::Normalize(direction);
+  geom::Vec3 norm0 = geom::Normalize(normal);
+  geom::Vec3 norm2 = geom::Cross(dir,norm0);
+  geom::Vec3 norm1 = geom::Cross(norm2,dir);
+  geom::Mat3 rmat(dir[0],norm1[0],norm2[0],
+                  dir[1],norm1[1],norm2[1],
+                  dir[2],norm1[2],norm2[2]);
+  
+  geom::Quat quat(rmat);
+  quat_value[0]=quat.w;
+  quat_value[1]=quat.x;
+  quat_value[2]=quat.y;
+  quat_value[3]=quat.z;
+}
+
+void SplineEntry::FromQuat() 
+{
+  /* 
+     assert orthornormal system since direction was
+     probably adjusted for curvature
+  */
+  // TODO: this seems broken
+  geom::Quat quat(quat_value[0],quat_value[1],quat_value[2],quat_value[3]);
+  geom::Mat3 rmat = quat.ToRotationMatrix();
+  geom::Vec3 norm0 = geom::Normalize(geom::Vec3(rmat(0,1),rmat(1,1),rmat(2,1)));
+  geom::Vec3 dir = geom::Normalize(direction);
+  geom::Vec3 norm2 = geom::Normalize(geom::Cross(dir,norm0));
+  normal = geom::Normalize(geom::Cross(norm2,dir));
+}
+
 ////////////////////////////
 
 
+Spline::Spline():
+  entry_list_()
+{}
+
+
+SplineEntry& Spline::AddEntry(const geom::Vec3& pos, const geom::Vec3& dir, const geom::Vec3& normal, float rad, const Color& c1, const Color& c2, int type)
+{
+  entry_list_.push_back(SplineEntry(pos,
+                                    geom::Normalize(dir),
+                                    geom::Normalize(normal),
+                                    rad,c1,c2,type));
+  entry_list_.back().ToQuat();
+  return entry_list_.back();
+}
+
 static int bsplineGen(float *x,float *y, int n, float yp1, float ypn, float *y2);
 static int bsplineGet(float *xa, float *ya, float *y2a, int n, float x, float *y);
 
 #define SPLINE_ENTRY_INTERPOLATE(COMPONENT)             \
     for(int c=0;c<size;++c) {                           \
-      yc[c]=entry_list.at(c). COMPONENT ;		\
+      yc[c]=entry_list_[c]. COMPONENT ;                 \
     }                                                   \
     bsplineGen(xp,yp,size,1.0e30,1.0e30,y2p);           \
-    for(int c=0;c<size-1;++c) {                         \
+    for(int c=0;c<size;++c) {                           \
       for(int d=0;d<nsub;++d) {                         \
         float u=static_cast<float>(c*nsub+d)*i_nsub;    \
         float v=0.0;                                    \
         bsplineGet(xp,yp,y2p,size,u,&v);                \
-        sublist.at(c*nsub+d). COMPONENT = v;		\
+        sublist[c*nsub+d]. COMPONENT = v;               \
       }                                                 \
-      float u=static_cast<float>((size-1)*nsub)*i_nsub;	\
-      float v=0.0;                                      \
-      bsplineGet(xp,yp,y2p,size,u,&v);                  \
-      sublist.at((size-1)*nsub). COMPONENT = v;		\
     }                                                   
 
-SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub)
+SplineEntryList Spline::Generate(int nsub) const
 {
   if(nsub<=0) {
-    return entry_list;
+    return entry_list_;
   }
-  int size=entry_list.size();
-  if (size<2) {
-    return entry_list;
+  int size=entry_list_.size();
+  if (size==0) {
+    return entry_list_;
   }
-  // we want to go to the last point, but not beyond
-  int ipsize=(size-1)*nsub+1;
+  int ipsize=(size)*nsub;
   float i_nsub=1.0/static_cast<float>(nsub);
   std::vector<float> xc(size);
   std::vector<float> yc(size);
@@ -140,8 +184,9 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub)
   // create sublist with enough entries
   SplineEntryList sublist(ipsize);
 
-  // interpolate color
+  // interpolate internal quaternion and color
   for(int k=0;k<4;++k) {
+    SPLINE_ENTRY_INTERPOLATE(quat_value[k]);
     SPLINE_ENTRY_INTERPOLATE(color1[k]);
     SPLINE_ENTRY_INTERPOLATE(color2[k]);
   }
@@ -158,14 +203,14 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub)
   // assign direction and normal
   // entity trace has the same algorithm
 
-  geom::Vec3 p0 = sublist.at(0).position;
-  geom::Vec3 p1 = sublist.at(1).position;
-  geom::Vec3 p2 = ipsize>2 ? sublist.at(2).position : p1+(p1-p0);
+  geom::Vec3 p0 = sublist[0].position;
+  geom::Vec3 p1 = sublist[1].position;
+  geom::Vec3 p2 = sublist[2].position;
   // normal of 0 is set at the end
-  sublist.at(0).direction=geom::Normalize(p1-p0);
-  sublist.at(0).v1=geom::Normalize(sublist.at(0).v1);
-  geom::Vec3 orth = geom::Cross(sublist.at(0).direction,sublist.at(0).v1);
-  sublist.at(0).v0 = geom::Normalize(geom::Cross(orth,sublist.at(0).direction));
+  sublist[0].direction=geom::Normalize(p1-p0);
+  sublist[0].v1=geom::Normalize(sublist[0].v1);
+  geom::Vec3 orth = geom::Cross(sublist[0].direction,sublist[0].v1);
+  sublist[0].v0 = geom::Normalize(geom::Cross(orth,sublist[0].direction));
 
   // reference normal to avoid twisting
   //geom::Vec3 nref=geom::Normalize(geom::Cross(p0-p1,p2-p1));
@@ -175,83 +220,88 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub)
     geom::Vec3 p12 = p2-p1;
     // correction for perfectly aligned consecutive directions
     if(p10==-p12 || p10==p12) p12+=geom::Vec3(0.001,0.001,0.001);
-    sublist.at(i).normal=geom::Normalize(geom::Cross(p10,p12));
+    sublist[i].normal=geom::Normalize(geom::Cross(p10,p12));
     // paranoid error checking due to occasional roundoff troubles
     float cosw = geom::Dot(geom::Normalize(p10),geom::Normalize(p12));
     cosw = std::min(float(1.0),std::max(float(-1.0),cosw));
     float omega=0.5*acos(cosw);
-    orth=geom::AxisRotation(sublist.at(i).normal, -omega)*p12;
-    sublist.at(i).direction=geom::Normalize(geom::Cross(sublist.at(i).normal,orth));
+    orth=geom::AxisRotation(sublist[i].normal, -omega)*p12;
+    sublist[i].direction=geom::Normalize(geom::Cross(sublist[i].normal,orth));
     // twist avoidance
-    sublist.at(i).v1=geom::Normalize(sublist.at(i).v1);
-    orth = geom::Cross(sublist.at(i).direction,sublist.at(i).v1);
-    sublist.at(i).v0 = geom::Normalize(geom::Cross(orth,sublist.at(i).direction));
-    if(geom::Dot(sublist.at(i-1).v0,sublist.at(i).v0)<0.0) {
-      sublist.at(i).v0=-sublist.at(i).v0;
-      //sublist.at(i).nflip = !sublist.at(i).nflip;
+    sublist[i].v1=geom::Normalize(sublist[i].v1);
+    orth = geom::Cross(sublist[i].direction,sublist[i].v1);
+    sublist[i].v0 = geom::Normalize(geom::Cross(orth,sublist[i].direction));
+    if(geom::Dot(sublist[i-1].v0,sublist[i].v0)<0.0) {
+      sublist[i].v0=-sublist[i].v0;
+      //sublist[i].nflip = !sublist[i].nflip;
     }
 
     // avoid twisting
-    //if(geom::Dot(sublist.at(i).normal,nref)<0.0) sublist.at(i).normal=-sublist.at(i).normal;
-    //nref=sublist.at(i).normal;
+    //if(geom::Dot(sublist[i].normal,nref)<0.0) sublist[i].normal=-sublist[i].normal;
+    //nref=sublist[i].normal;
     // skip over shift for the last iteration
     if(i==sublist.size()-2) break;
     // shift to i+1 for next iteration
-    p0 = sublist.at(i).position;
-    p1 = sublist.at(i+1).position;
-    p2 = sublist.at(i+2).position;
+    p0 = sublist[i].position;
+    p1 = sublist[i+1].position;
+    p2 = sublist[i+2].position;
   }
   // assign remaining ones
-  sublist.at(0).normal=sublist.at(1).normal;
-  sublist.at(i+1).direction=geom::Normalize(p2-p1);
-  sublist.at(i+1).normal=sublist.at(i).normal;
-  sublist.at(i+1).v1=geom::Normalize(sublist.at(i+1).v1);
-  orth = geom::Cross(sublist.at(i+1).direction,sublist.at(i+1).v1);
-  sublist.at(i+1).v0 = geom::Normalize(geom::Cross(orth,sublist.at(i+1).direction));
+  sublist[0].normal=sublist[1].normal;
+  sublist[i+1].direction=geom::Normalize(p2-p1);
+  sublist[i+1].normal=sublist[i].normal;
+  sublist[i+1].v1=geom::Normalize(sublist[i+1].v1);
+  orth = geom::Cross(sublist[i+1].direction,sublist[i+1].v1);
+  sublist[i+1].v0 = geom::Normalize(geom::Cross(orth,sublist[i+1].direction));
 
   // hack
   // TODO: merge this with above routine
   for(unsigned int i=0;i<sublist.size()-1;++i) {
-    sublist.at(i).normal = sublist.at(i).v0;
+    sublist[i].normal = sublist[i].v0;
   }
 
   // finally the non-interpolated type
   // with some tweaks for proper strand rendering
-  for(int c=0;c<size-1;++c) {
-    int type1=entry_list[c].type;
-    int type2=entry_list[std::min(c+1,size-1)].type;
+  for(int c=0;c<size;++c) {
     for(int d=0;d<nsub;++d) {
-      sublist.at(c*nsub+d).type=entry_list[c].type;
-      sublist.at(c*nsub+d).type1=type1;
-      sublist.at(c*nsub+d).type2=type2;
-      sublist.at(c*nsub+d).frac=float(d)/float(nsub);
+      sublist[c*nsub+d].type=entry_list_[c].type;
+      int type1=entry_list_[c].type;
+      int type2=entry_list_[std::min(c+1,size-1)].type;
+      //int type0=entry_list_[std::max(0,c-1)].type;
+      if(type1==2 && type2==3) {
+        type1=2;
+        type2=2;
+      } else if(type1==3) {
+        type1=4;
+        // uncommenting this causes the strand arrows
+        // to blend into a tip instead of the n+1
+        // profile - gives visual artefacts
+        //type2=3;
+      }
+      sublist[c*nsub+d].type1=type1;
+      sublist[c*nsub+d].type2=type2;
+      sublist[c*nsub+d].frac=float(d)/float(nsub);
     }
   }                                                   
-  int type1=entry_list.back().type;
-  int type2=type1;
-  sublist.back().type=entry_list.back().type;
-  sublist.back().type1=type1;
-  sublist.back().type2=type2;
-  sublist.back().frac=0.0;
 
   // the nflip flags for helices for correct inside/outside assignment
   int c=0;
   bool nflip=false;
-  while(c<nsub*(size-1)) {
+  while(c<nsub*size-1) {
     int cstart=c;
-    if(sublist.at(c).type==1 && sublist.at(c+1).type==1) {
-      geom::Vec3 n = geom::Normalize(geom::Cross(sublist.at(c).normal,
-                                                 sublist.at(c).direction));
-      geom::Vec3 p0 = sublist.at(c).position+n;
-      geom::Vec3 q0 = sublist.at(c).position-n;
+    if(sublist[c].type==1 && sublist[c+1].type==1) {
+      geom::Vec3 n = geom::Normalize(geom::Cross(sublist[c].normal,
+                                                 sublist[c].direction));
+      geom::Vec3 p0 = sublist[c].position+n;
+      geom::Vec3 q0 = sublist[c].position-n;
       float psum=0.0;
       float qsum=0.0;
       ++c;
-      while(sublist.at(c).type==1 && c<nsub*size) {
-        n = geom::Normalize(geom::Cross(sublist.at(c).normal,
-                                        sublist.at(c).direction));
-        geom::Vec3 p1 = sublist.at(c).position+n;
-        geom::Vec3 q1 = sublist.at(c).position-n;
+      while(sublist[c].type==1 && c<nsub*size) {
+        n = geom::Normalize(geom::Cross(sublist[c].normal,
+                                        sublist[c].direction));
+        geom::Vec3 p1 = sublist[c].position+n;
+        geom::Vec3 q1 = sublist[c].position-n;
         psum+=Length(p1-p0);
         qsum+=Length(q1-q0);
         p0=p1;
@@ -261,7 +311,7 @@ SplineEntryList Spline::Generate(const SplineEntryList& entry_list, int nsub)
       
       nflip = qsum>psum;
       for(int cc=cstart;cc<c;++cc) {
-        sublist.at(c).nflip=nflip;
+        sublist[cc].nflip=nflip;
       }
     } else {
       ++c;
diff --git a/modules/gfx/src/impl/entity_detail.hh b/modules/gfx/src/impl/entity_detail.hh
index a077d2d54..7cf19d622 100644
--- a/modules/gfx/src/impl/entity_detail.hh
+++ b/modules/gfx/src/impl/entity_detail.hh
@@ -115,14 +115,7 @@ 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),
-    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)
+    type(0)
   {
   }
   SplineEntry(const geom::Vec3& p, 
@@ -130,17 +123,22 @@ struct DLLEXPORT_OST_GFX SplineEntry {
               const geom::Vec3& n,
               float r,
               const Color& c1, const Color& c2,
-              unsigned int t):
+              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)
   {
   }
 
+  void ToQuat();
+
+  void FromQuat();
+
   geom::Vec3 position,direction,normal;
   Color color1, color2;
+  float quat_value[4];
   float rad;
-  unsigned int type;
-  unsigned int type1, type2;
+  int type;
+  int type1, type2;
   float frac;
   geom::Vec3 v0,v1,v2; // helper vectors
   bool nflip;
@@ -151,7 +149,20 @@ typedef std::vector<SplineEntryList> SplineEntryListList;
 
 class DLLEXPORT_OST_GFX Spline {
 public:
-  static SplineEntryList Generate(const SplineEntryList& entry_list,int nsub);
+
+public:
+  // ctor
+  Spline();
+
+  // add entry at a given position, with direction and normal vectors
+  SplineEntry& AddEntry(const geom::Vec3& pos, const geom::Vec3& dir, 
+                        const geom::Vec3& normal, float r, const Color& col1, 
+                        const Color& col2, int type);
+
+  SplineEntryList Generate(int nsub) const;
+
+private:
+  SplineEntryList entry_list_;
 };
 
 }}} // ns
diff --git a/modules/gfx/src/impl/entity_renderer.hh b/modules/gfx/src/impl/entity_renderer.hh
index 4d90f97e0..28a932abf 100644
--- a/modules/gfx/src/impl/entity_renderer.hh
+++ b/modules/gfx/src/impl/entity_renderer.hh
@@ -24,8 +24,8 @@
 */
 
 
-#if defined(GetAtomProps)
-#undef GetAtomProps
+#if defined(GetProp)
+#undef GetProp
 #endif
 #include <vector>
 
@@ -160,8 +160,6 @@ public:
   void FlagPositionsDirty();
 
   void Debug(unsigned int flags);
-
-  IndexedVertexArray& VA() {return va_;}
 protected:
   virtual void SetName(const String& name);
 
@@ -180,13 +178,12 @@ protected:
   DirtyFlags            sel_state_;
   DirtyFlags            state_;
   unsigned int          debug_flags_;
-  float                 opacity_;
 };
 
 //Simplify color ops
 struct ByElementGetCol {
   Color ColorOfAtom(mol::AtomHandle& atom) const{
-    return GfxObj::Ele2Color(atom.GetElement());
+    return GfxObj::Ele2Color(atom.GetAtomProps().element);
   }
 };
 
diff --git a/modules/gfx/src/impl/line_trace_renderer.cc b/modules/gfx/src/impl/line_trace_renderer.cc
index 45e2b63fa..b0279b71f 100644
--- a/modules/gfx/src/impl/line_trace_renderer.cc
+++ b/modules/gfx/src/impl/line_trace_renderer.cc
@@ -17,16 +17,12 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 
-/*
-  Authors: Marco Biasini, Ansgar Philippsen
-*/
-
 #include "line_trace_renderer.hh"
 #include <ost/gfx/entity.hh>
 
 namespace ost { namespace gfx { namespace impl {
 
-LineTraceRenderer::LineTraceRenderer(BackboneTrace* trace): 
+LineTraceRenderer::LineTraceRenderer(BackboneTrace& trace): 
   TraceRendererBase(trace, 1), options_(new LineTraceRenderOptions())
 {
   this->SetName("Fast Trace");
@@ -45,9 +41,10 @@ void LineTraceRenderer::PrepareRendering()
   }
 }
 
-void LineTraceRenderer::PrepareRendering(const BackboneTrace& trace_subset,
+void LineTraceRenderer::PrepareRendering(TraceSubset& trace_subset,
                                          IndexedVertexArray& va, bool is_sel)
 {
+
   const Color& sel_clr=this->GetSelectionColor();
   if(options_!=NULL){
     va.Clear();
@@ -59,27 +56,54 @@ void LineTraceRenderer::PrepareRendering(const BackboneTrace& trace_subset,
     va.SetLineWidth(options_->GetLineWidth());
     va.SetPointSize(options_->GetLineWidth());
     va.SetAALines(options_->GetAALines());
-    for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) {
-      const NodeEntryList& nl=trace_subset.GetList(node_list);
-
-      if (nl.size()<2) {
-	continue;
+    for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) {
+      const NodeListSubset& nl=trace_subset[node_list];
+
+      if (nl.GetSize()==2) {
+        VertexID p0, p1;
+        if (nl.AtStart()==0) {
+          p0=va.Add(nl[0].atom.GetPos(), geom::Vec3(),
+                    is_sel ? sel_clr : nl[0].color1);
+          p1=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, 
+                    geom::Vec3(), is_sel ? sel_clr : nl[1].color1);
+        } else {
+          p0=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, 
+                    geom::Vec3(), is_sel ? sel_clr : nl[0].color1);
+          p1=va.Add(nl[1].atom.GetPos(), 
+                    geom::Vec3(), is_sel ? sel_clr : nl[1].color1);
+        }
+        va.AddLine(p0, p1);        
+        continue;
       }
-
-      VertexID p0=va.Add(nl[0].atom.GetPos(), geom::Vec3(),
-			 is_sel ? sel_clr : nl[0].color1);
-
-      for (unsigned int i=1; i<nl.size()-1;++i) {
+      if (nl.GetSize()<3) {
+        continue;
+      }
+      VertexID p0;      
+      if (nl.AtStart()==0) {
+        p0=va.Add(nl[0].atom.GetPos(), geom::Vec3(),
+                  is_sel ? sel_clr : nl[0].color1);
+      } else {
+        p0=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, 
+                  geom::Vec3(), is_sel ? sel_clr : nl[0].color1);
+      }
+      for (int i=1; i<nl.GetSize()-1;++i) {
         const NodeEntry& entry=nl[i];
         VertexID p1 =va.Add(entry.atom.GetPos(), geom::Vec3(), 
                             is_sel ? sel_clr : entry.color1);
         va.AddLine(p0, p1);
         p0=p1;
       }
-      const NodeEntry& entry=nl.back();      
-      VertexID p1 =va.Add(entry.atom.GetPos(), geom::Vec3(), 
-			  is_sel ? sel_clr : entry.color1);
-      va.AddLine(p0, p1);
+      const NodeEntry& entry=nl[nl.GetSize()-1];      
+      if (nl.AtEnd()==0) {
+        VertexID p1 =va.Add(entry.atom.GetPos(), geom::Vec3(), 
+                            is_sel ? sel_clr : entry.color1);
+        va.AddLine(p0, p1);                            
+      } else {
+        geom::Vec3 p=(entry.atom.GetPos()+nl[nl.GetSize()-2].atom.GetPos())*0.5;
+        VertexID p1 =va.Add(p, geom::Vec3(), 
+                            is_sel ? sel_clr : entry.color1);
+        va.AddLine(p0, p1);
+      }
     }
   }
   sel_state_=0;
@@ -88,6 +112,7 @@ void LineTraceRenderer::PrepareRendering(const BackboneTrace& trace_subset,
 
 void LineTraceRenderer::Render()
 {
+
 }
 
 bool LineTraceRenderer::CanSetOptions(RenderOptionsPtr& render_options)
diff --git a/modules/gfx/src/impl/line_trace_renderer.hh b/modules/gfx/src/impl/line_trace_renderer.hh
index fc2a2ad87..d4b904e0f 100644
--- a/modules/gfx/src/impl/line_trace_renderer.hh
+++ b/modules/gfx/src/impl/line_trace_renderer.hh
@@ -16,11 +16,6 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
-
-/*
-  Authors: Marco Biasini, Ansgar Philippsen
-*/
-
 #ifndef OST_GFX_IMPL_LINE_TRACE_RENDERER_HH
 #define OST_GFX_IMPL_LINE_TRACE_RENDERER_HH
 
@@ -41,10 +36,10 @@ using namespace impl;
 /// \internal
 class DLLEXPORT_OST_GFX LineTraceRenderer: public TraceRendererBase {
 public:
-  LineTraceRenderer(BackboneTrace* trace);
+  LineTraceRenderer(BackboneTrace& trace);
 
   virtual void PrepareRendering();
-  virtual void PrepareRendering(const BackboneTrace& trace_subset, 
+  virtual void PrepareRendering(TraceSubset& trace_subset, 
                                 IndexedVertexArray& va, bool is_sel);
   virtual void Render();
 
diff --git a/modules/gfx/src/impl/sline_renderer.cc b/modules/gfx/src/impl/sline_renderer.cc
index 7ae7f937a..6d1fe022d 100644
--- a/modules/gfx/src/impl/sline_renderer.cc
+++ b/modules/gfx/src/impl/sline_renderer.cc
@@ -16,18 +16,13 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
-
-/*
-  Authors: Marco Biasini, Ansgar Philippsen
-*/
-
 #include "sline_renderer.hh"
 
 #include <ost/gfx/entity.hh>
 
 namespace ost { namespace gfx { namespace impl {
 
-SlineRenderer::SlineRenderer(BackboneTrace* trace): 
+SlineRenderer::SlineRenderer(BackboneTrace& trace): 
   TraceRendererBase(trace, 3), options_(new SlineRenderOptions()) 
 {
   this->SetName("Fast Spline");
@@ -45,7 +40,7 @@ void SlineRenderer::PrepareRendering()
   }
 }
 
-void SlineRenderer::PrepareRendering(const BackboneTrace& trace_subset, 
+void SlineRenderer::PrepareRendering(TraceSubset& trace_subset, 
                                      IndexedVertexArray& va, bool is_sel)
 {
   const Color& sel_clr=this->GetSelectionColor();
@@ -61,24 +56,30 @@ void SlineRenderer::PrepareRendering(const BackboneTrace& trace_subset,
     va.SetLineWidth(options_->GetLineWidth());
     va.SetPointSize(options_->GetLineWidth());
     va.SetAALines(options_->GetAALines());
-    for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) {
+    for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) {
       // first build the spline
-      SplineEntryList spl;
-      const NodeEntryList& nl=trace_subset.GetList(node_list);
-      if(nl.empty()) continue;
-      for (unsigned int i=0; i<nl.size();++i) {
+      Spline spl;
+      const NodeListSubset& nl=trace_subset[node_list];
+      assert(nl.GetSize() && "node list subset with zero eles encountered!");
+      for (int i=0; i<nl.GetSize();++i) {
         const NodeEntry& entry=nl[i];
-        SplineEntry ee(entry.atom.GetPos(), entry.direction,
-                       entry.normal, entry.rad, 
-                       is_sel ? sel_clr : entry.color1, 
-                       is_sel ? sel_clr : entry.color2, 0);
+        SplineEntry& ee = spl.AddEntry(entry.atom.GetPos(), entry.direction,
+                                       entry.normal, entry.rad, 
+                                       is_sel ? sel_clr : entry.color1, 
+                                       is_sel ? sel_clr : entry.color2, 0);
         ee.v1 = entry.v1;
-        spl.push_back(ee);
       }
-      SplineEntryList sel = Spline::Generate(spl,spline_detail);      
-      SplineEntryList::const_iterator sit=sel.begin();
+      SplineEntryList sel = spl.Generate(spline_detail);      
+      SplineEntryList::const_iterator sit=sel.begin(), 
+                                     send=sel.end()-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;
+      }
       VertexID p0=va.Add(sit->position, geom::Vec3(),sit->color1);
-      for (++sit; sit!=sel.end(); ++sit) {
+      for (++sit; sit<send; ++sit) {
         VertexID p1 = va.Add(sit->position, geom::Vec3(),sit->color1);
         va.AddLine(p0,p1);
         p0=p1;
diff --git a/modules/gfx/src/impl/sline_renderer.hh b/modules/gfx/src/impl/sline_renderer.hh
index 4c08ba3b0..b264fc4b6 100644
--- a/modules/gfx/src/impl/sline_renderer.hh
+++ b/modules/gfx/src/impl/sline_renderer.hh
@@ -16,11 +16,6 @@
 // along with this library; if not, write to the Free Software Foundation, Inc.,
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
-
-/*
-  Authors: Marco Biasini, Ansgar Philippsen
-*/
-
 #ifndef OST_GFX_SLINE_RENDERER_HH
 #define OST_GFX_SLINE_RENDERER_HH
 
@@ -37,7 +32,7 @@ namespace ost { namespace gfx { namespace impl {
 /// \internal
 class DLLEXPORT_OST_GFX SlineRenderer: public TraceRendererBase {
 public:
-  SlineRenderer(BackboneTrace* trace);
+  SlineRenderer(BackboneTrace& trace);
 
   virtual void PrepareRendering();
 
@@ -48,7 +43,7 @@ public:
   virtual ~SlineRenderer();
 
 private:
-  void PrepareRendering(const BackboneTrace& subset, IndexedVertexArray& va, 
+  void PrepareRendering(TraceSubset& subset, IndexedVertexArray& va, 
                         bool is_sel);
   SlineRenderOptionsPtr options_;
 };
diff --git a/modules/gfx/src/impl/trace_renderer.cc b/modules/gfx/src/impl/trace_renderer.cc
index eacf3f0a9..29691cc1d 100644
--- a/modules/gfx/src/impl/trace_renderer.cc
+++ b/modules/gfx/src/impl/trace_renderer.cc
@@ -17,10 +17,6 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 
-/*
-   Authors: Marco Biasini, Ansgar Philippsen
-*/
-
 #include <ost/gfx/entity.hh>
 #include <ost/gfx/povray.hh>
 
@@ -29,7 +25,7 @@
 
 namespace ost { namespace gfx { namespace impl {
 
-TraceRenderer::TraceRenderer(BackboneTrace* trace): 
+TraceRenderer::TraceRenderer(BackboneTrace& trace): 
   TraceRendererBase(trace, 1), options_(new TraceRenderOptions())
 {
   this->SetName("Trace");
@@ -47,7 +43,8 @@ void TraceRenderer::PrepareRendering()
   }
 }
 
-void TraceRenderer::PrepareRendering(BackboneTrace& trace_subset,
+#if 1
+void TraceRenderer::PrepareRendering(TraceSubset& trace_subset,
                                      IndexedVertexArray& va, bool is_sel)
 {
   float plus=is_sel ? 0.05: 0.0;
@@ -58,14 +55,14 @@ void TraceRenderer::PrepareRendering(BackboneTrace& trace_subset,
     va.SetCullFace(true);
     va.SetColorMaterial(true);
     va.SetTwoSided(false);
-    for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) {
-      const NodeEntryList& nl=trace_subset.GetList(node_list);
+    for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) {
+      const NodeListSubset& nl=trace_subset[node_list];
       mol::AtomHandle a1=nl[0].atom;
       va.AddSphere(SpherePrim(a1.GetPos(),
                               options_->GetTubeRadius()+plus,
                               is_sel ? sel_clr : nl[0].color1),
                    options_->GetArcDetail());
-      for(unsigned int i=1;i<nl.size();++i) {
+      for(int i=1;i<nl.GetSize();++i) {
         mol::AtomHandle a2=nl[i].atom;
         va.AddSphere(SpherePrim(a2.GetPos(),
                                 options_->GetTubeRadius()+plus,
@@ -86,18 +83,169 @@ void TraceRenderer::PrepareRendering(BackboneTrace& trace_subset,
   state_=0;
 }
 
+#else
+
+void TraceRenderer::PrepareRendering(TraceSubset& trace_subset,
+                                     IndexedVertexArray& va, bool is_sel)
+{
+  const Color& sel_clr=this->GetSelectionColor();
+  float radius=options_->GetTubeRadius();
+  if (is_sel) {
+    radius+=0.1;
+  }
+  int n=8*options_->GetArcDetail();
+  if(options_!=NULL) {
+    va.SetLighting(true);
+    va.SetCullFace(false);
+    for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) {
+      const NodeListSubset& nl=trace_subset[node_list];
+      geom::Vec3 cursor_pos;
+      geom::Mat3 cursor_ori;
+      if (nl.GetSize()==2) {
+        VertexID p0, p1;
+        if (nl.AtStart()==0) {
+          p0=va.Add(nl[0].atom.GetPos(), geom::Vec3(),
+                    is_sel ? sel_clr : nl[0].color1);
+          p1=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, 
+                    geom::Vec3(), is_sel ? sel_clr : nl[1].color1);
+        } else {
+          p0=va.Add((nl[0].atom.GetPos()+nl[1].atom.GetPos())/2, 
+                    geom::Vec3(), is_sel ? sel_clr : nl[0].color1);
+          p1=va.Add(nl[1].atom.GetPos(), 
+                    geom::Vec3(), is_sel ? sel_clr : nl[1].color1);
+        }
+        va.AddLine(p0, p1);        
+        continue;
+      }
+      if (nl.GetSize()<3) {
+        continue;
+      }
+      VertexID p0;
+      geom::Vec3 z=geom::Normalize(nl[1].atom.GetPos()-nl[0].atom.GetPos());
+      geom::Vec3 y=geom::OrthogonalVector(z);
+      geom::Vec3 x=geom::Cross(y, z);
+      cursor_ori=geom::Mat3(x[0], y[0], z[0], x[1], y[1], z[1], 
+                            x[2], y[2], z[2]);    
+      if (nl.AtStart()==0) {
+        cursor_pos=nl[0].atom.GetPos();
+      } else {
+        cursor_pos=(nl[0].atom.GetPos()+nl[1].atom.GetPos())/2;
+      }
+      p0=this->AddCappedProfile(va, is_sel? sel_clr : nl[0].color1, 
+                                cursor_pos, cursor_ori, radius, true, n);
+      for (int i=1; i<nl.GetSize()-1;++i) {
+        const NodeEntry& entry=nl[i];
+        geom::Vec3 old_dir=geom::Normalize(entry.atom.GetPos()-cursor_pos);
+        cursor_pos=entry.atom.GetPos();
+
+        geom::Vec3 z=geom::Normalize(nl[i+1].atom.GetPos()-cursor_pos);
+        geom::Vec3 y=geom::Normalize(geom::Cross(z, cursor_ori.GetCol(0)));
+        geom::Vec3 x=geom::Normalize(geom::Cross(y, z));
+        geom::Vec3 iz=geom::Normalize(cursor_ori.GetCol(2)+z);
+
+        geom::Vec3 iy=geom::Normalize(geom::Cross(cursor_ori.GetCol(2), z));
+        geom::Vec3 ix=geom::Normalize(geom::Cross(iy, iz));
+
+        geom::Mat3 i_ori=geom::Mat3(ix[0], iy[0], iz[0], ix[1], iy[1], iz[1], 
+                                    ix[2], iy[2], iz[2]);                           
+        cursor_ori=geom::Mat3(x[0], y[0], z[0], x[1], y[1], z[1], 
+                              x[2], y[2], z[2]);
+        // TODO. The intersection of two cylinders is an ellipse. Use an 
+        //        elliptic profile instead of a circular profile.
+        VertexID p1=this->AddCircularProfile(va, is_sel ? sel_clr : entry.color1,
+                                             cursor_pos, i_ori, radius, n);
+        this->ConnectProfiles(p0, p1, n, old_dir, va);
+        p0=p1;
+      }
+      const NodeEntry& entry=nl[nl.GetSize()-1];      
+      if (nl.AtEnd()==0) {
+        cursor_pos=entry.atom.GetPos();
+      } else {
+        cursor_pos=(entry.atom.GetPos()+nl[nl.GetSize()-2].atom.GetPos())*0.5;
+      }
+      VertexID p1 =this->AddCappedProfile(va, is_sel ? sel_clr : entry.color1, 
+                                          cursor_pos, cursor_ori, 
+                                          radius, false, n);
+      this->ConnectProfiles(p0, p1, n, cursor_ori.GetCol(2), va);      
+    }
+  }
+  sel_state_=0;
+  state_=0;
+}
+#endif
+
+VertexID TraceRenderer::AddCappedProfile(IndexedVertexArray& va, 
+                                         const Color& color,
+                                         const geom::Vec3& center, 
+                                         const geom::Mat3& ori, float radius, 
+                                         bool flip_normal,
+                                         int n)
+{
+   VertexID center_id=va.Add(center, geom::Vec3(), color);
+   VertexID first=this->AddCircularProfile(va, color, center, ori, radius, n);
+   for (int i=0; i<n; ++i) {
+     va.AddTriN(center_id, first+i, first+((i+1) % n));
+   }
+   return first;
+}
+
+VertexID TraceRenderer::AddCircularProfile(IndexedVertexArray& va, 
+                                           const Color& color,
+                                           const geom::Vec3& center, 
+                                           const geom::Mat3& ori, 
+                                           float radius, 
+                                           int n)
+{
+  float delta_angle=2*M_PI/n;
+  VertexID f=0;
+  geom::Vec3 normal=ori.GetRow(2);
+  for (int i=0; i<n; ++i) {
+    geom::Vec3 normal=ori*geom::Vec3(cos(i*delta_angle), 
+                                     sin(i*delta_angle), 0.0);
+    VertexID x=va.Add(center+normal*radius, normal, color);
+    if (i==0) {
+      f=x;
+    }
+  }
+  return f;
+}
+
+void TraceRenderer::ConnectProfiles(VertexID prof0, VertexID prof1, int n, 
+                                    const geom::Vec3& dir, 
+                                    IndexedVertexArray& va)
+{
+  // avoid twisting
+  int off=0;
+  float best=0.0;
+  geom::Vec3 pp=va.GetVert(prof0);
+  for (int i=0; i<n; ++i) {
+    geom::Vec3 dir2=geom::Normalize(va.GetVert(prof1+i)-pp);
+    float dot=fabs(geom::Dot(dir, dir2));
+    if (best<dot) {
+      best=dot;
+      off=i;
+    }
+  }
+  for (int i=0; i<n; ++i) {
+    VertexID i1=prof1+((i+off) % n), i2=prof1+((i+off+1) % n);
+    VertexID  i3=prof0+i, i4=prof0+((i+1)%n);
+    va.AddTriN(i1, i2, i3);
+    va.AddTriN(i2, i3, i4);
+  }
+}
+
 void TraceRenderer::RenderPov(PovState& pov, const std::string& name)
 {
   pov.write_merge_or_union(name);
 
-  for (int node_list=0; node_list<trace_subset_.GetListCount(); ++node_list) {
-    const NodeEntryList& nl=trace_subset_.GetList(node_list);
+  for (int node_list=0; node_list<trace_subset_.GetSize(); ++node_list) {
+    const NodeListSubset& nl=trace_subset_[node_list];
 
     geom::Vec3 p0=nl[0].atom.GetPos();
     float rad0=0.2;
     Color col0=nl[0].color1;
     pov.write_sphere(p0,rad0,col0,name);
-    for (unsigned int i=1; i<nl.size();++i) {
+    for (int i=1; i<nl.GetSize();++i) {
       geom::Vec3 p1=nl[i].atom.GetPos();
       float rad1=0.2;
       Color col1=nl[i].color1;
@@ -114,6 +262,11 @@ void TraceRenderer::RenderPov(PovState& pov, const std::string& name)
   pov.inc() << " }\n";
 }
 
+void TraceRenderer::Render()
+{
+
+}
+
 bool TraceRenderer::CanSetOptions(RenderOptionsPtr& render_options)
 {
   return render_options.get()->GetRenderMode()==RenderMode::TRACE;
diff --git a/modules/gfx/src/impl/trace_renderer.hh b/modules/gfx/src/impl/trace_renderer.hh
index e8f9cff3b..77cb8d3da 100644
--- a/modules/gfx/src/impl/trace_renderer.hh
+++ b/modules/gfx/src/impl/trace_renderer.hh
@@ -20,9 +20,8 @@
 #define OST_GFX_IMPL_TRACE_RENDERER_HH
 
 /*
-   Authors: Marco Biasini, Ansgar Philippsen
-*/
-
+   Author: Marco Biasini
+ */
 #include <ost/gfx/impl/backbone_trace.hh>
 #include <ost/gfx/impl/entity_detail.hh>
 #include <ost/gfx/impl/trace_renderer_base.hh>
@@ -38,12 +37,12 @@ using namespace impl;
 /// \internal
 class DLLEXPORT_OST_GFX TraceRenderer: public TraceRendererBase {
 public:
-  TraceRenderer(BackboneTrace* trace);
+  TraceRenderer(BackboneTrace& trace);
 
   virtual void PrepareRendering();
-  virtual void PrepareRendering(BackboneTrace& trace_subset, 
+  virtual void PrepareRendering(TraceSubset& trace_subset, 
                                 IndexedVertexArray& va, bool is_sel);
-
+  virtual void Render();
   virtual void RenderPov(PovState& pov, const std::string& name);
 
   virtual bool CanSetOptions(RenderOptionsPtr& render_options);
@@ -52,6 +51,14 @@ public:
 
   virtual ~TraceRenderer();
 private:
+  VertexID AddCappedProfile(IndexedVertexArray& va, const Color& color,
+                            const geom::Vec3& center, const geom::Mat3& ori, 
+                            float radius, bool flip_normal, int n);
+  VertexID AddCircularProfile(IndexedVertexArray& va, const Color& color,
+                              const geom::Vec3& center, const geom::Mat3& ori,
+                              float radius, int n);
+  void ConnectProfiles(VertexID prof1, VertexID prof2, int n, 
+                       const geom::Vec3& dir, IndexedVertexArray& va);
   TraceRenderOptionsPtr  options_;
 };
 
diff --git a/modules/gfx/src/impl/trace_renderer_base.cc b/modules/gfx/src/impl/trace_renderer_base.cc
index 9231e929c..46084a880 100644
--- a/modules/gfx/src/impl/trace_renderer_base.cc
+++ b/modules/gfx/src/impl/trace_renderer_base.cc
@@ -17,10 +17,6 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 //------------------------------------------------------------------------------
 
-/*
-  Authors: Marco Biasini, Ansgar Philippsen
-*/
-
 #include <ost/gfx/scene.hh>
 
 #include "trace_renderer_base.hh"
@@ -38,15 +34,15 @@ void set_node_entry_color(NodeEntry& e, ColorMask mask,
 }
 
 template <typename T1>
-inline void apply_color_op(TraceRendererBase* rend, BackboneTrace& trace_subset, T1 get_col, const ColorOp& op)
+inline void apply_color_op(TraceRendererBase* rend, TraceSubset& trace_subset, T1 get_col, const ColorOp& op)
 {
   rend->UpdateViews();
   ColorMask mask = op.GetMask();
   if(op.IsSelectionOnly()){
     mol::Query q(op.GetSelection());
-    for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) {
-      NodeEntryList& nl=trace_subset.GetList(node_list);
-      for (unsigned int i=0; i<nl.size();++i) {
+    for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) {
+      NodeListSubset& nl=trace_subset[node_list];
+      for (int i=0; i<nl.GetSize();++i) {
         if (q.IsAtomSelected(nl[i].atom)) {
           Color clr =get_col.ColorOfAtom(nl[i].atom);
           set_node_entry_color(nl[i],mask,clr);
@@ -56,9 +52,9 @@ inline void apply_color_op(TraceRendererBase* rend, BackboneTrace& trace_subset,
   }
   else{
     mol::EntityView view = op.GetView();
-    for (int node_list=0; node_list<trace_subset.GetListCount(); ++node_list) {
-      NodeEntryList& nl=trace_subset.GetList(node_list);
-      for (unsigned int i=0; i<nl.size();++i) {
+    for (int node_list=0; node_list<trace_subset.GetSize(); ++node_list) {
+      NodeListSubset& nl=trace_subset[node_list];
+      for (int i=0; i<nl.GetSize();++i) {
         if(view.FindAtom(nl[i].atom)){
           Color clr =get_col.ColorOfAtom(nl[i].atom);
           set_node_entry_color(nl[i],mask,clr);
@@ -71,8 +67,8 @@ inline void apply_color_op(TraceRendererBase* rend, BackboneTrace& trace_subset,
 
 } //ns
 
-TraceRendererBase::TraceRendererBase(BackboneTrace* trace, int n):
-  trace_(trace), trace_subset_(*trace), sel_subset_()
+TraceRendererBase::TraceRendererBase(BackboneTrace& trace, int n):
+  trace_(trace), trace_subset_(trace, n), sel_subset_(trace, n)
 {
 }
 
@@ -84,37 +80,44 @@ void TraceRendererBase::UpdateViews()
 {
   if (state_ & DIRTY_VIEW) {
     mol::EntityView view=this->GetEffectiveView();
-    trace_subset_=trace_->CreateSubset(view);
+    trace_subset_.Update(view);
     state_&=~DIRTY_VIEW;    
   }
   if (this->HasSelection() && (sel_state_ & DIRTY_VIEW)) {
-    sel_subset_ = trace_->CreateSubset(sel_);
+    sel_subset_.Update(sel_);
     sel_state_&=~DIRTY_VIEW;    
   }
 }
 
 geom::AlignedCuboid TraceRendererBase::GetBoundingBox() const
 {
-  geom::Vec3 mmin(std::numeric_limits<float>::max(),
-		  std::numeric_limits<float>::max(),
-		  std::numeric_limits<float>::max());
-  geom::Vec3 mmax(-std::numeric_limits<float>::max(),
-		  -std::numeric_limits<float>::max(),
-		  -std::numeric_limits<float>::max());
-		  
+  geom::Vec3 mmin, mmax;
   assert(!(state_ & DIRTY_VIEW));
-  for (int node_list=0; node_list<trace_subset_.GetListCount(); ++node_list) {
-    const NodeEntryList& nl=trace_subset_.GetList(node_list);
-    for (unsigned int i=0; i<nl.size();++i) {
+  bool empty=true;
+  for (int node_list=0; node_list<trace_subset_.GetSize(); ++node_list) {
+    // first build the spline
+    Spline spl;
+    const NodeListSubset& nl=trace_subset_[node_list];
+    for (int i=0; i<nl.GetSize();++i) {
       const NodeEntry& entry=nl[i];      
+      empty=false;
       geom::Vec3 p=entry.atom.GetPos();
-      mmin=geom::Min(mmin, p);
-      mmax=geom::Max(mmax, p);
+      if (node_list+i==0) {
+        mmin=p;
+        mmax=p;
+      } else {
+        mmin=geom::Min(mmin, p);
+        mmax=geom::Max(mmax, p);
+      }
     }
   }  
+  if (empty) {
+    throw Error("Can't calculate bounding box of empty renderer");
+  }
   return geom::AlignedCuboid(mmin, mmax);
 }
 
+
 void TraceRendererBase::Apply(const gfx::ByElementColorOp& op)
 {
   apply_color_op(this,trace_subset_,ByElementGetCol(),op);
@@ -149,16 +152,16 @@ void TraceRendererBase::Apply(const gfx::EntityViewColorOp& op)
 bool TraceRendererBase::HasDataToRender() const
 {
   assert(!(state_ & DIRTY_VIEW));
-  return this->trace_subset_.GetListCount()>0;
+  return this->trace_subset_.GetSize()>0;
 }
 
 void TraceRendererBase::set_node_colors(const Color& col, const mol::Query& q, 
                                         ColorMask mask)
 {
   this->UpdateViews();
-  for (int node_list=0; node_list<trace_subset_.GetListCount(); ++node_list) {
-    NodeEntryList& nl=trace_subset_.GetList(node_list);
-    for (unsigned int i=0; i<nl.size();++i) {
+  for (int node_list=0; node_list<trace_subset_.GetSize(); ++node_list) {
+    NodeListSubset& nl=trace_subset_[node_list];
+    for (int i=0; i<nl.GetSize();++i) {
       if(q.IsAtomSelected(nl[i].atom)) {
         set_node_entry_color(nl[i],mask,col);
       }
@@ -167,6 +170,13 @@ void TraceRendererBase::set_node_colors(const Color& col, const mol::Query& q,
   state_|=DIRTY_VA;  
 }
 
+void TraceRendererBase::set_node_entry_color(NodeEntry& e, ColorMask mask, 
+                                             const Color& c)
+{
+  if (mask & MAIN_COLOR) e.color1=c;
+  if (mask & DETAIL_COLOR) e.color2=c;
+}
+
 void TraceRendererBase::PickAtom(const geom::Line3& line, Real line_width,
                                  mol::AtomHandle& picked_atom)
 {
@@ -180,9 +190,9 @@ void TraceRendererBase::PickAtom(const geom::Line3& line, Real line_width,
   }
 
   mol::AtomHandle atom;
-  for (int node_list=0; node_list<trace_subset_.GetListCount(); ++node_list) {
-    NodeEntryList& nl=trace_subset_.GetList(node_list);
-    for (unsigned int i=0; i<nl.size();++i) {
+  for (int node_list=0; node_list<trace_subset_.GetSize(); ++node_list) {
+    NodeListSubset& nl=trace_subset_[node_list];
+    for (int i=0; i<nl.GetSize();++i) {
       geom::Vec3 p=nl[i].atom.GetPos();
       float dist = geom::Distance(line, p);
       if(dist<=max_dist) {
diff --git a/modules/gfx/src/impl/trace_renderer_base.hh b/modules/gfx/src/impl/trace_renderer_base.hh
index 36e3b9602..b102e1cc2 100644
--- a/modules/gfx/src/impl/trace_renderer_base.hh
+++ b/modules/gfx/src/impl/trace_renderer_base.hh
@@ -20,8 +20,8 @@
 #define OST_GFX_IMPL_TRACE_RENDERER_BASE_HH
 
 /*
-  Authors: Marco Biasini, Ansgar Philippsen
-*/
+  Author: Marco Biasini
+ */
 
 #include <ost/gfx/module_config.hh>
 #include <ost/gfx/impl/entity_renderer.hh>
@@ -35,11 +35,11 @@ namespace ost { namespace gfx { namespace impl {
 ///     \ref "line trace" LineTraceRenderer and 
 ///     \ref "smooth trace" SlineRenderer.
 /// 
-/// All trace-based entity renderers share a  common instance of BackboneTrace
-/// (which is held by gfx::Entity); it encapulates a smoothed C-alpha trace.
+/// The trace-based entity renderer share a  common instance of BackboneTrace 
+/// that encapulates a smoothed C-alpha trace.
 class DLLEXPORT_OST_GFX TraceRendererBase : public EntityRenderer {
 public:
-  TraceRendererBase(BackboneTrace* trace, int overshoot);
+  TraceRendererBase(BackboneTrace& trace, int overshoot);
   
   virtual geom::AlignedCuboid GetBoundingBox() const;  
   
@@ -63,10 +63,12 @@ public:
 protected:
   
   void set_node_colors(const Color& c, const mol::Query& q, ColorMask mask);
+  void set_node_entry_color(NodeEntry& e, ColorMask mask, const Color& c);
+  
 
-  BackboneTrace* trace_;
-  BackboneTrace trace_subset_;
-  BackboneTrace sel_subset_;
+  BackboneTrace& trace_;
+  TraceSubset    trace_subset_;
+  TraceSubset    sel_subset_;
 };
 
 }}}
diff --git a/modules/gfx/src/offscreen_buffer.hh b/modules/gfx/src/offscreen_buffer.hh
index df2ca183f..c033d8816 100644
--- a/modules/gfx/src/offscreen_buffer.hh
+++ b/modules/gfx/src/offscreen_buffer.hh
@@ -22,54 +22,86 @@
 /*
   Wraps GL offscreen rendering per platform
 
-  boilerplate header, includes platform dependent stuff
+  Authors: Ansgar Philippsen, Marco Biasini
 */
 
-#include <vector>
+#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
 
 namespace ost { namespace gfx {
 
-class OffscreenBufferFormat
-{
+/// \brief offscreen management
+class OffscreenBuffer {
 public:
-  OffscreenBufferFormat(): cbits(8),abits(8),dbits(12),accum(false),multisample(false),samples(0) {}
+  
+  /// \brief singleton interface
+  static OffscreenBuffer& Instance();
 
-  unsigned int cbits,abits,dbits; // color, alpha, depth bits
-  bool accum;
-  bool multisample;
-  unsigned int samples;
-};
+  /// \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);
 
-}} // ns
+  /// \brief returns true if offscreen rendering context is available
+  bool IsValid() 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
+  /// \brief returns true between Begin/End bracket
+  bool IsActive() const;
 
-   OffscreenBuffer interface:
+private:
+  OffscreenBuffer(int width, int height, int r_bits, int b_bits, 
+                  int g_bits, int a_bits, int depth_bits);
 
-   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();
-*/
+  OffscreenBuffer(const OffscreenBuffer& b) {}
+  OffscreenBuffer& operator=(const OffscreenBuffer& b) {return *this;}
+  
+  int width_;
+  int height_;
+  bool valid_;
+  bool active_;
 
 #if defined(__linux__)
-#include "impl/glx_offscreen_buffer.hh"
+  Display*    dpy_;
+  GLXFBConfig* fbconfig_;
+  GLXPbuffer  pbuffer_;
+  GLXContext  context_;
+  GLXContext  old_context_;
+  GLXDrawable        old_dr1_;
+  GLXDrawable        old_dr2_;
+
 #elif defined(__APPLE__)
-#include "impl/cgl_offscreen_buffer.hh"
+
+  CGLPBufferObj      pbuffer_;
+  CGLContextObj      context_;
+  CGLPixelFormatObj  pix_format_;
+  CGLContextObj      old_context_;
+
 #elif defined(_WIN32)
-#include "impl/wgl_offscreen_buffer.hh"
-#else
-#error platform not found for offscreen rendering
+/*  HPBUFFERARB        pbuffer_;
+  HGLRC              context_; //rendering context
+  HGLRC              old_context_;
+  
+  HDC                dev_context_;//device context
+  HDC                old_dev_context_;
+  */
 #endif
+
+  GLint       old_vp_[4];
+};
  
-#ifdef Complex
-#  undef Complex
-#endif
+}}
 
 #endif
diff --git a/modules/gfx/src/prim_list.cc b/modules/gfx/src/prim_list.cc
index 4c2395c14..2302dc7fe 100644
--- a/modules/gfx/src/prim_list.cc
+++ b/modules/gfx/src/prim_list.cc
@@ -31,9 +31,7 @@ PrimList::PrimList(const String& name):
   points_(),
   lines_(),
   radius_(0.5),
-  diameter_(0.5),
-  sphere_detail_(4),
-  arc_detail_(4)
+  diameter_(0.5)
 {}
 
 void PrimList::Clear()
@@ -97,6 +95,8 @@ void PrimList::CustomPreRenderGL(bool flag)
     } else {
       render_simple();
     }
+  } else {
+    RefreshVA(va_);
   }
 }
 
@@ -155,28 +155,12 @@ void PrimList::SetDiameter(float d)
 {
   diameter_=d;
   Scene::Instance().RequestRedraw();
-  FlagRebuild();
 }
 
 void PrimList::SetRadius(float r)
 {
   radius_=r;
   Scene::Instance().RequestRedraw();
-  FlagRebuild();
-}
-
-void PrimList::SetSphereDetail(unsigned int d)
-{
-  sphere_detail_=d;
-  Scene::Instance().RequestRedraw();
-  FlagRebuild();
-}
-
-void PrimList::SetArcDetail(unsigned int d)
-{
-  arc_detail_=d;
-  Scene::Instance().RequestRedraw();
-  FlagRebuild();
 }
 
 void PrimList::SetColor(const Color& c)
@@ -185,7 +169,6 @@ void PrimList::SetColor(const Color& c)
     it->color=c;
   }
   Scene::Instance().RequestRedraw();
-  FlagRebuild();
 }
 
 
diff --git a/modules/gfx/src/prim_list.hh b/modules/gfx/src/prim_list.hh
index fbac2cffc..1de40d7f9 100644
--- a/modules/gfx/src/prim_list.hh
+++ b/modules/gfx/src/prim_list.hh
@@ -98,12 +98,6 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj
   /// \brief set global prims color, overriding individual ones
   void SetColor(const Color& c);
 
-  void SetSphereDetail(unsigned int d);
-  unsigned int GetSphereDetail() const {return sphere_detail_;}
-
-  void SetArcDetail(unsigned int d);
-  unsigned int GetArcDetail() const {return arc_detail_;}
-
  protected:
   virtual void CustomPreRenderGL(bool flag);
 
@@ -112,8 +106,6 @@ class DLLEXPORT_OST_GFX PrimList: public GfxObj
   LineEntryList lines_;
   float radius_;
   float diameter_;
-  unsigned int sphere_detail_;
-  unsigned int arc_detail_;
   
   void render_simple();
   void render_custom();
diff --git a/modules/gfx/src/render_options/cartoon_render_options.cc b/modules/gfx/src/render_options/cartoon_render_options.cc
index f50d28a5b..da5d2e703 100644
--- a/modules/gfx/src/render_options/cartoon_render_options.cc
+++ b/modules/gfx/src/render_options/cartoon_render_options.cc
@@ -39,12 +39,10 @@ CartoonRenderOptions::CartoonRenderOptions(bool force_tube):
   helix_thickness_(0.2),
   helix_ecc_(0.3),
   helix_profile_(1),
-  helix_mode_(0),
   strand_width_(1.2),
   strand_thickness_(0.2),
   strand_ecc_(0.3),
-  strand_profile_(1),
-  strand_mode_(0)
+  strand_profile_(1)
 {}
 
 RenderMode::Type CartoonRenderOptions::GetRenderMode(){
@@ -68,17 +66,12 @@ void CartoonRenderOptions::ApplyRenderOptions(RenderOptionsPtr render_options){
   smooth_factor_=options->GetNormalSmoothFactor();
   tube_radius_=options->GetTubeRadius();
   tube_ratio_=options->GetTubeRatio();
-  tube_profile_=options->GetTubeProfileType();
   helix_width_=options->GetHelixWidth();
   helix_thickness_=options->GetHelixThickness();
   helix_ecc_=options->GetHelixEcc();
-  helix_profile_=options->GetHelixProfileType();
-  helix_mode_=options->GetHelixMode();
   strand_width_=options->GetStrandWidth();
   strand_thickness_=options->GetStrandThickness();
   strand_ecc_=options->GetStrandEcc();
-  strand_profile_=options->GetStrandProfileType();
-  strand_mode_=options->GetStrandMode();
   this->NotifyStateChange();
 }
 
@@ -203,17 +196,6 @@ void CartoonRenderOptions::SetHelixProfileType(unsigned int t)
   this->NotifyStateChange();
 }
 
-unsigned int CartoonRenderOptions::GetHelixMode() const
-{
-  return helix_mode_;
-}
-
-void CartoonRenderOptions::SetHelixMode(unsigned int m)
-{
-  helix_mode_=m;
-  this->NotifyStateChange();
-}
-
 void CartoonRenderOptions::SetStrandWidth(float strand_width){
   if(strand_width_ != strand_width){
     strand_width_= strand_width>0.0 ? strand_width : strand_width_;
@@ -258,17 +240,6 @@ void CartoonRenderOptions::SetStrandProfileType(unsigned int t)
   this->NotifyStateChange();
 }
 
-unsigned int CartoonRenderOptions::GetStrandMode() const
-{
-  return strand_mode_;
-}
-
-void CartoonRenderOptions::SetStrandMode(unsigned int m)
-{
-  strand_mode_=m;
-  this->NotifyStateChange();
-}
-
 float CartoonRenderOptions::GetMaxRad() const{
   float max_rad=std::max(float(3.0),tube_radius_*tube_ratio_);
   max_rad=std::max(max_rad,tube_radius_);
diff --git a/modules/gfx/src/render_options/cartoon_render_options.hh b/modules/gfx/src/render_options/cartoon_render_options.hh
index 98f490430..092fafe69 100644
--- a/modules/gfx/src/render_options/cartoon_render_options.hh
+++ b/modules/gfx/src/render_options/cartoon_render_options.hh
@@ -67,8 +67,6 @@ public:
   virtual float GetHelixEcc() const;
   virtual unsigned int GetHelixProfileType() const;
   virtual void SetHelixProfileType(unsigned int);
-  virtual unsigned int GetHelixMode() const;
-  virtual void SetHelixMode(unsigned int);
 
   virtual void SetStrandWidth(float strand_width);
   virtual float GetStrandWidth() const;
@@ -78,8 +76,6 @@ public:
   virtual float GetStrandEcc() const;
   virtual unsigned int GetStrandProfileType() const;
   virtual void SetStrandProfileType(unsigned int);
-  virtual unsigned int GetStrandMode() const;
-  virtual void SetStrandMode(unsigned int);
 
   float GetMaxRad() const;
 
@@ -100,13 +96,10 @@ private:
   float helix_thickness_;
   float helix_ecc_;
   unsigned int helix_profile_;
-  unsigned int helix_mode_;
   float strand_width_;
   float strand_thickness_;
   float strand_ecc_;
   unsigned int strand_profile_;
-  unsigned int strand_mode_;
-
 };
 
 typedef boost::shared_ptr<CartoonRenderOptions> CartoonRenderOptionsPtr;
diff --git a/modules/gfx/src/render_options/cpk_render_options.cc b/modules/gfx/src/render_options/cpk_render_options.cc
index 797fcf760..611db0f48 100644
--- a/modules/gfx/src/render_options/cpk_render_options.cc
+++ b/modules/gfx/src/render_options/cpk_render_options.cc
@@ -28,7 +28,7 @@ namespace gfx {
 
 CPKRenderOptions::CPKRenderOptions(): sphere_detail_(4) {
 #if OST_SHADER_SUPPORT_ENABLED
-  cpk_mode_=0;
+  cpk_mode_=1;
 #else
   cpk_mode_=0;
 #endif
diff --git a/modules/gfx/src/render_pass.hh b/modules/gfx/src/render_pass.hh
index 00c5f7c23..dd7a34a33 100644
--- a/modules/gfx/src/render_pass.hh
+++ b/modules/gfx/src/render_pass.hh
@@ -33,10 +33,8 @@ typedef enum {
   /// \brief renders objects with solid color as used for shadow map
   ///     generation
   OPAQUE_RENDER_PASS,
-  /// \ brief for transparent objects
-  TRANSPARENT_RENDER_PASS
 } RenderPass;
  
 }}
 
-#endif
+#endif
\ No newline at end of file
diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index 4ded0a30c..c85abc13d 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -42,6 +42,7 @@
 #include "gl_helper.hh"
 
 #include <ost/config.hh>
+#include "offscreen_buffer.hh"
 #include "scene.hh"
 #include "input.hh"
 #include "gfx_node.hh"
@@ -50,7 +51,6 @@
 #include "bitmap_io.hh"
 #include "entity.hh"
 #include "povray.hh"
-#include "offscreen_buffer.hh"
 
 #if OST_SHADER_SUPPORT_ENABLED
 # include "shader.hh"
@@ -115,7 +115,6 @@ Scene::Scene():
   texture_id_(),
   auto_autoslab_(true),
   offscreen_flag_(false),
-  main_offscreen_buffer_(0),
   selection_mode_(1),
   test_flag_(false),
   tmp_tex_(),
@@ -144,11 +143,6 @@ 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};
@@ -157,11 +151,6 @@ void Scene::SetFogColor(const Color& c)
   RequestRedraw();
 }
 
-Color Scene::GetFogColor() const
-{
-  return fog_color_;
-}
-
 void Scene::SetShadow(bool f)
 {
   shadow_flag_=f;
@@ -192,10 +181,9 @@ void set_light_dir(Vec3 ld)
 
 void Scene::InitGL()
 {
-  LOGN_DEBUG("scene: initializing GL state");
+  LOG_DEBUG("scene: initializing GL state" << std::endl);
 
 #if OST_SHADER_SUPPORT_ENABLED
-  LOGN_DEBUG("scene: shader pre-gl");
   Shader::Instance().PreGLInit();
 #endif
 
@@ -246,29 +234,9 @@ 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);
@@ -281,7 +249,6 @@ 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");
 
@@ -293,7 +260,7 @@ void Scene::InitGL()
 
 void Scene::RequestRedraw()
 {
-  if (win_ && !offscreen_flag_) {
+  if (win_) {
     win_->DoRefresh();
   }
 }
@@ -311,11 +278,6 @@ void Scene::SetBackground(const Color& c)
   RequestRedraw();
 }
 
-Color Scene::GetBackground() const
-{
-  return background_;
-}
-
 Viewport Scene::GetViewport() const
 {
   Viewport vp;
@@ -344,7 +306,6 @@ void Scene::SetCenter(const Vec3& cen)
   float delta_z = tcen[2]-transform_.GetTrans()[2];
 
   transform_.SetCenter(cen);
-  transform_.SetTrans(Vec3(0,0,transform_.GetTrans()[2]));
   SetNearFar(znear_+delta_z,zfar_+delta_z);
   RequestRedraw();  
 }
@@ -545,37 +506,6 @@ namespace {
     GfxObjP node;
   };
 
-#if 0
-  struct RegexFindObj: public GfxNodeVisitor {
-    RegexFindObj(const String& rs): reg(), valid(false), node() {
-      try {
-        reg = boost::regex(rs);
-        valid = true;
-      } catch (boost::regex_error& e) {
-        LOGN_ERROR("invalid regex");
-      }
-    }
-
-    virtual bool VisitNode(GfxNode* n, const Stack& st) {
-      return true;
-    }
-
-    virtual void VisitObject(GfxObj* o, const Stack& st) {
-      if(boost::regex_match(o->GetName(),reg)) {
-        GfxNodeP nn = o->shared_from_this();
-        GfxObjP oo = dyn_cast<GfxObj>(nn);
-        if(oo) {
-          olist.push_back(oo);
-        }
-      }
-    }
-
-    boost::regex reg;
-    bool valid;
-    std::vector<GfxObjP> olist;
-  };
-#endif
-
   struct FindNode2: public GfxNodeVisitor {
     FindNode2(GfxNodeP n): node(n), found(false) {}
     virtual bool VisitNode(GfxNode* n, const Stack& st) {
@@ -615,14 +545,6 @@ void Scene::Add(const GfxNodeP& n, bool redraw)
   }
 
   LOG_DEBUG("scene: graphical object added @" << n.get() << std::endl);
-
-  if(root_node_->GetChildCount()==0) {
-    GfxObjP go = boost::dynamic_pointer_cast<GfxObj>(n);
-    if(go) {
-      SetCenter(go->GetCenter());
-    }
-  }
-
   root_node_->Add(n);
   if (redraw) {
     this->RequestRedraw();
@@ -1201,54 +1123,24 @@ uint Scene::GetSelectionMode() const
   return selection_mode_;
 }
 
-void Scene::StartOffscreenMode(unsigned int width, unsigned int height)
-{
-  if(main_offscreen_buffer_) return;
-  main_offscreen_buffer_ = new OffscreenBuffer(width,height,OffscreenBufferFormat(),true);
+namespace {
 
-  if(!main_offscreen_buffer_->IsValid()) {
-    LOGN_ERROR("error during offscreen buffer creation");
-    delete main_offscreen_buffer_;   
-    main_offscreen_buffer_=0;
-    return;
+struct OffscreenSwitcher
+{
+  OffscreenSwitcher()
+  {
+    LOGN_TRACE("offscreen begin");
+    OffscreenBuffer::Instance().Begin();
   }
-  old_vp_[0]=vp_width_;
-  old_vp_[1]=vp_height_;
-  main_offscreen_buffer_->MakeActive();
-  offscreen_flag_=true;
-  root_node_->ContextSwitch();
 
-#if OST_SHADER_SUPPORT_ENABLED
-  String shader_name = Shader::Instance().GetCurrentName();
-#endif
-  LOGN_DEBUG("initializing GL");
-  this->InitGL();
-  LOGN_DEBUG("setting viewport");
-  Resize(width,height);
-  LOGN_DEBUG("updating fog settings");
-  update_fog();
-  glDrawBuffer(GL_FRONT);
-#if OST_SHADER_SUPPORT_ENABLED
-  LOGN_DEBUG("activating shader");
-  Shader::Instance().Activate(shader_name);
-#endif
-}
-
-void Scene::StopOffscreenMode()
-{
-  if(main_offscreen_buffer_) {
-    if (win_) {
-      win_->MakeActive();
-    }
-    delete main_offscreen_buffer_;
-    main_offscreen_buffer_=0;
-    Scene::Instance().SetViewport(old_vp_[0],old_vp_[1]);
-    offscreen_flag_=false;
-    root_node_->ContextSwitch();
-    glDrawBuffer(GL_BACK);
-    update_fog();
+  ~OffscreenSwitcher()
+  {
+    LOGN_TRACE("offscreen end");
+    OffscreenBuffer::Instance().End();
   }
-}
+};
+
+} // anon ns
 
 void Scene::Export(const String& fname, unsigned int width,
                    unsigned int height, bool transparent)
@@ -1264,101 +1156,61 @@ void Scene::Export(const String& fname, unsigned int width,
     return;
   }
 
-  GLint old_vp[4];
-  glGetIntegerv(GL_VIEWPORT,old_vp);
-  bool old_flag=offscreen_flag_;
-  if(!main_offscreen_buffer_) {
-    try {
-      LOGN_DEBUG("creating a " << width <<"x" << height << " offscreen rendering buffer");
-      OffscreenBuffer ob(width,height,OffscreenBufferFormat(),true);
-      
-      if(!ob.IsValid()) {
-        LOGN_ERROR("error during offscreen buffer creation");
-        return;
-      }
-      
-      ob.MakeActive();
-      offscreen_flag_=true;
-#if 1
-#if OST_SHADER_SUPPORT_ENABLED
-      String shader_name = Shader::Instance().GetCurrentName();
-#endif
-      LOGN_DEBUG("initializing GL");
-      this->InitGL();
-      LOGN_DEBUG("setting viewport");
-      SetViewport(width,height);
-      LOGN_DEBUG("reseting projection");
-      ResetProjection();
-      LOGN_DEBUG("updating fog settings");
-      update_fog();
-      glDrawBuffer(GL_FRONT);
+  offscreen_flag_=true;
+  LOGN_TRACE("offscreen resize");
+  OffscreenBuffer::Instance().Resize(width, height);
+  try {
+    // ensures that context is switched back when this goes out of scope
+    OffscreenSwitcher offscreen_switch;
 
 #if OST_SHADER_SUPPORT_ENABLED
-      LOGN_DEBUG("activating shader");
-      Shader::Instance().Activate(shader_name);
+    String shader_name = Shader::Instance().GetCurrentName();
 #endif
-      root_node_->ContextSwitch();
+    LOGN_TRACE("initializing GL");
+    this->InitGL();
+    LOGN_TRACE("setting viewport");
+    SetViewport(width,height);
+    LOGN_TRACE("reseting projection");
+    ResetProjection();
+    LOGN_TRACE("updating fog settings");
+    update_fog();
+    glDrawBuffer(GL_FRONT);
+    //this->flag_all_dirty();
+#if OST_SHADER_SUPPORT_ENABLED
+    LOGN_TRACE("activating shader");
+    Shader::Instance().Activate(shader_name);
 #endif
-    } catch (std::exception& e) {
-      LOGN_ERROR("exception during offscreen rendering initialization: " << e.what());
-      throw;
+    LOGN_TRACE("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");
+    if (transparent) {
+      glPixelTransferf(GL_ALPHA_BIAS, 0.0);
+    } else {
+      // shift alpha channel by one to make sure pixels are read out as opaque
+      glPixelTransferf(GL_ALPHA_BIAS, 1.0);
     }
-  } else {
-    LOGN_DEBUG("using active main offscreen buffer");
-  }
-  LOGN_DEBUG("rendering into offscreen buffer");
-  this->RenderGL();
-  // make sure drawing operations are finished
-  glFlush();
-  glFinish();
 
-  unsigned int width2=width;
-  unsigned int height2=height;
-  if(main_offscreen_buffer_!=NULL) {
-    // use settings from active main buffer
-    width2=old_vp[2];
-    height2=old_vp[3];
-  }
-  boost::shared_array<uchar> img_data(new uchar[width2*height2*4]);
-      
-  LOGN_DEBUG("setting background transparency");
-  if (transparent) {
-    glPixelTransferf(GL_ALPHA_BIAS, 0.0);
-  } else {
-    // shift alpha channel by one to make sure pixels are read out as opaque
-    glPixelTransferf(GL_ALPHA_BIAS, 1.0);
-  }
-  
-  LOGN_DEBUG("reading framebuffer pixels");
-  glReadBuffer(GL_FRONT);
-  glReadPixels(0,0,width2,height2,GL_RGBA,GL_UNSIGNED_BYTE,img_data.get());
+    LOGN_TRACE("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,width2,height2,img_data.get());
-  
-  if(!main_offscreen_buffer_) {
-    LOGN_DEBUG("switching back to main context");
-    if (!win_) {
-      return;
-    }
-    win_->MakeActive();
-    Scene::Instance().SetViewport(old_vp[2],old_vp[3]);
-    offscreen_flag_=old_flag;
-    root_node_->ContextSwitch();
-    glDrawBuffer(GL_BACK);
-    LOGN_DEBUG("updating fog");
-    update_fog();
-  } else {
-    // nothing needs to happen here, main offscreen buffer was active, and stays active
-  }
+    LOGN_DEBUG("calling bitmap export");
+    BitmapExport(fname,ext,width,height,img_data.get());
+  } catch (...) {
+    // noop
+  } // offscreen_switch goes out of scope
+  offscreen_flag_=false;
+  glDrawBuffer(GL_BACK);
+  LOGN_TRACE("updating fog");
+  update_fog();
 }
 
 void Scene::Export(const String& fname, bool transparent)
 {
-  if(!win_ && !main_offscreen_buffer_) {
-    LOGN_ERROR("Export without dimensions either requires an interactive session \nor an active offscreen mode (scene.StartOffscreenMode(W,H))");
-    return;
-  }
   int d_index=fname.rfind('.');
   if (d_index==-1) {
     LOGN_ERROR("no file extension specified");
@@ -1372,12 +1224,6 @@ void Scene::Export(const String& fname, bool transparent)
   GLint vp[4];
   glGetIntegerv(GL_VIEWPORT,vp);
 
-  if(main_offscreen_buffer_) {
-    this->RenderGL();
-    glFlush();
-    glFinish();
-  }
-
   if (transparent) {
     glPixelTransferf(GL_ALPHA_BIAS, 0.0);
   } else {
@@ -1703,6 +1549,11 @@ bool Scene::InOffscreenMode() const
   return offscreen_flag_;
 }
 
+void Scene::SetOffscreenMode()
+{
+  OffscreenBuffer::Instance().Begin();
+}
+
 float Scene::ElapsedTime() const
 {
 #ifndef _MSC_VER
diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh
index 6c88204d2..d86e46a6a 100644
--- a/modules/gfx/src/scene.hh
+++ b/modules/gfx/src/scene.hh
@@ -46,7 +46,6 @@
 namespace ost { namespace gfx {
 
 class InputEvent;
-class OffscreenBuffer;
 
 typedef std::vector<SceneObserver*>  SceneObserverList;
 
@@ -93,15 +92,9 @@ 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);
 
@@ -191,15 +184,13 @@ class DLLEXPORT_OST_GFX Scene {
   /// \name Export
   //@}
   /// \brief export scene into a bitmap, rendering into offscreen of given size
-  /// if a main offscreen buffer is active (\sa StartOffscreenMode), then the
-  /// dimensions here are ignored
   void Export(const String& fname, unsigned int w,
               unsigned int h, bool transparent=true);
 
   /// \brief export snapshot of current scene
   void Export(const String& fname, bool transparent=true);
 
-  /// \brief export scene into povray files named fname.pov and fname.inc
+  /// \brief export scene into povray files names fname.pov and fname.inc
   void ExportPov(const std::string& fname, const std::string& wdir=".");
   //@}
   /// \brief entry point for gui events (internal use)
@@ -234,9 +225,6 @@ 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);
   
@@ -323,27 +311,15 @@ class DLLEXPORT_OST_GFX Scene {
   
   bool InOffscreenMode() const;
 
+  /// \brief internal use
+  static void SetOffscreenMode();
+
   /// \brief switch into test mode (internal use)
   void SetTestMode(bool t);
 
   float ElapsedTime() const;
 
   Viewport GetViewport() const;
-
-  /*!
-    This method has two different tasks. 
-
-    During interactive rendering, it facilitates export 
-    into an offscreen buffer with Scene::Export(file,width,height)
-    by avoiding repeated initializations of the GL state, e.g.
-    during animation rendering.
-
-    During batch mode, this is the only way to get meaningful
-    functionality with the gfx module
-  */
-  void StartOffscreenMode(unsigned int w, unsigned int h);
-  /// \brief stops offline rendering in interactive mode
-  void StopOffscreenMode();
   
   // temporary interface
   void ActivateShader(const String& name);
@@ -406,9 +382,7 @@ private:
   GLuint texture_id_;
   bool auto_autoslab_;
 
-  bool offscreen_flag_; // a simple indicator whether in offscreen mode or not
-  OffscreenBuffer* main_offscreen_buffer_; // not null if a main offscreen buffer is present
-  uint old_vp_[2]; // used by the offline rendering code
+  bool offscreen_flag_;
 
   uint selection_mode_;
 
diff --git a/modules/gfx/src/shader/fraglight_lf_fs.glsl b/modules/gfx/src/shader/fraglight_lf_fs.glsl
index ad34b9f40..7ffec79b8 100644
--- a/modules/gfx/src/shader/fraglight_lf_fs.glsl
+++ b/modules/gfx/src/shader/fraglight_lf_fs.glsl
@@ -2,7 +2,6 @@ uniform bool lighting_flag;
 uniform bool two_sided_flag;
 uniform bool fog_flag;
 uniform bool occlusion_flag;
-uniform vec2 ambient_weight;
 varying vec4 ambient_color;
 
 // copy from basic_fl_vs !
@@ -35,34 +34,31 @@ void main()
     vec4 amb = vec4(0.0);
     vec4 diff = vec4(0.0);
     vec4 spec = vec4(0.0);
+    vec4 color = vec4(0.0);
 
-    vec4 color = gl_Color;
+    /* 
+      For ambient occlusion, this blends the local ambient color together with
+      the fragment color at intensity given my the ambient material settings;
+      ambient_color defaults to gl_Color, so for non ambient-occluded scenes,
+      this is a noop
+    */
+    vec4 diff_color = gl_Color;
     if(occlusion_flag) {
-      /* 
-        For ambient occlusion and local coloring, two effects are possible. 
-        (1) Blending of the original fragment color and the accumulated
-            color of the neighbouring fragments, by ambient_weight[0].
-        (2) Attenuating the resulting color intensity by the ambient occlusion,
-            modulated by ambient_weight[1]
-        Only the rgb values are affected, fragment opacity is unchanged
-      */
-
-      color.rgb = mix(gl_Color.rgb,ambient_color.rgb,ambient_weight[0]);
-      color.rgb = mix(color.rgb,ambient_color.aaa*color.rgb,ambient_weight[1]);
+      diff_color.rgb = mix(gl_Color.rgb,ambient_color.rgb,gl_FrontMaterial.ambient.rgb);
     }
 
     if(DirectionalLight(normal, gl_FrontMaterial.shininess, amb, diff, spec)) {
 
       color  = gl_FrontLightModelProduct.sceneColor  +
-               (amb  * gl_FrontMaterial.ambient * color) +
-               (diff * gl_FrontMaterial.diffuse * color) +
+               (amb  * gl_FrontMaterial.diffuse * diff_color * ambient_color.a) +
+               (diff * gl_FrontMaterial.diffuse * diff_color) +
                (spec * gl_FrontMaterial.specular);
     } else {
       DirectionalLight(-normal, gl_BackMaterial.shininess, amb, diff, spec);
 
       color = gl_BackLightModelProduct.sceneColor  +
-              (amb  * gl_BackMaterial.ambient * color) +
-              (diff * gl_BackMaterial.diffuse * color) +
+              (amb  * gl_BackMaterial.ambient * diff_color * ambient_color.a) +
+              (diff * gl_BackMaterial.diffuse * diff_color) +
               (spec * gl_BackMaterial.specular);
     }
     
diff --git a/modules/gfx/src/surface.cc b/modules/gfx/src/surface.cc
index 40db431fe..e0d08cdc1 100644
--- a/modules/gfx/src/surface.cc
+++ b/modules/gfx/src/surface.cc
@@ -43,10 +43,7 @@ Surface::Surface(const String& name, const mol::SurfaceHandle& sh):
   recalc_bb_(true)
 {
   // TODO replace with def mat for this gfx obj type
-  SetMatAmb(Color(0,0,0));
-  SetMatDiff(Color(1,1,1));
-  SetMatSpec(Color(0.2,0.2,0.2));
-  SetMatShin(48);
+  SetMat(0.0,1.0,0.2,48.0);
   Rebuild();
 }
 
@@ -167,11 +164,10 @@ geom::AlignedCuboid Surface::GetBoundingBox() const
 
 void Surface::CustomPreRenderGL(bool flag)
 {
-  va_.FlagRefresh();
   if(flag) {
     //Rebuild();
   } else {
-    //RefreshVA(va_);
+    RefreshVA(va_);
   }
 }
 
@@ -248,29 +244,28 @@ void Surface::ColorBy(const String& prop,
 
 void Surface::Apply(const gfx::UniformColorOp& op, bool store){
   if(store){
-    UniformColorOp* op_ptr = new UniformColorOp(op);
+	UniformColorOp* op_ptr = new UniformColorOp(op);
     this->AppendColorOp(op_ptr);
   }
   mol::Query q(op.GetSelection());
   gfx::Color col = op.GetColor();
   if(op.GetSelection()=="") {
-    for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) {
-      va_.SetColor(it->second,col);
-    }
+	for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) {
+	  va_.SetColor(it->second,col);
+	}
   } else {
-    for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) {
-      mol::AtomHandle ah = sh_.GetVertex(it->first).atom;
-      if(ah.IsValid()) {
-        if(q.IsAtomSelected(ah)) {
-          va_.SetColor(it->second,col);
-        }
-      }
-    }
+	for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) {
+	  mol::AtomHandle ah = sh_.GetVertex(it->first).atom;
+	  if(ah.IsValid()) {
+		if(q.IsAtomSelected(ah)) {
+		  va_.SetColor(it->second,col);
+		}
+	  }
+	}
   }
   FlagRefresh();
 }
-void Surface::Apply(const gfx::BasicGradientColorOp& op, bool store)
-{
+void Surface::Apply(const gfx::BasicGradientColorOp& op, bool store){
   if(store){
     BasicGradientColorOp* op_ptr = new BasicGradientColorOp(op);
     this->AppendColorOp(op_ptr);
@@ -284,24 +279,23 @@ void Surface::Apply(const gfx::BasicGradientColorOp& op, bool store)
   mol::EntityPropertyMapper epm(prop, level);
   std::vector<std::pair<VertexID,float> > v2v;
   for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) {
-    mol::AtomHandle ah = sh_.GetVertex(it->first).atom;
-    if(ah.IsValid()) {
-      float v = epm.Get(ah);
-      v2v.push_back(std::make_pair(it->second,v));
-      minv=std::min(minv,v);
-      maxv=std::max(maxv,v);
-    }
+	mol::AtomHandle ah = sh_.GetVertex(it->first).atom;
+	if(ah.IsValid()) {
+	  float v = epm.Get(ah);
+	  v2v.push_back(std::make_pair(it->second,v));
+	  minv=std::min(minv,v);
+	  maxv=std::max(maxv,v);
+	}
   }
-  
+
   // reuse values for speed optimization
   for(std::vector<std::pair<VertexID,float> >::const_iterator it=v2v.begin();it!=v2v.end();++it) {
-    va_.SetColor(it->first,gradient.GetColorAt(normalize(it->second,minv,maxv)));
+	va_.SetColor(it->first,gradient.GetColorAt(normalize(it->second,minv,maxv)));
   }
   FlagRefresh();
 }
 
-void Surface::Apply(const gfx::GradientLevelColorOp& op, bool store)
-{
+void Surface::Apply(const gfx::GradientLevelColorOp& op, bool store){
   if(store){
     GradientLevelColorOp* op_ptr = new GradientLevelColorOp(op);
     this->AppendColorOp(op_ptr);
@@ -315,16 +309,15 @@ void Surface::Apply(const gfx::GradientLevelColorOp& op, bool store)
   // for the attached atoms
   mol::EntityPropertyMapper epm(prop, level);
   for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) {
-    mol::AtomHandle ah = sh_.GetVertex(it->first).atom;
-    if(ah.IsValid()) {
-      va_.SetColor(it->second,gradient.GetColorAt(normalize(epm.Get(ah),minv,maxv)));
-    }
+	mol::AtomHandle ah = sh_.GetVertex(it->first).atom;
+	if(ah.IsValid()) {
+	  va_.SetColor(it->second,gradient.GetColorAt(normalize(epm.Get(ah),minv,maxv)));
+	}
   }
   FlagRefresh();
 }
 
-void Surface::Apply(const gfx::EntityViewColorOp& op, bool store)
-{
+void Surface::Apply(const gfx::EntityViewColorOp& op, bool store){
   if(store){
     EntityViewColorOp* op_ptr = new EntityViewColorOp(op);
     this->AppendColorOp(op_ptr);
@@ -335,15 +328,14 @@ void Surface::Apply(const gfx::EntityViewColorOp& op, bool store)
   float minv = op.GetMinV();
   float maxv = op.GetMaxV();
   for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) {
-    va_.SetColor(it->second,impl::MappedProperty(ev,prop,g,minv,maxv,
-                                                 sh_.GetVertex(it->first).position));
+  va_.SetColor(it->second,impl::MappedProperty(ev,prop,g,minv,maxv,
+                                               sh_.GetVertex(it->first).position));
   }
   FlagRefresh();
 }
-  
+
 #if OST_IMG_ENABLED
-void Surface::Apply(const gfx::MapHandleColorOp& op, bool store)
-{
+void Surface::Apply(const gfx::MapHandleColorOp& op, bool store){
   if(store){
     MapHandleColorOp* op_ptr = new MapHandleColorOp(op);
     this->AppendColorOp(op_ptr);
@@ -354,19 +346,17 @@ void Surface::Apply(const gfx::MapHandleColorOp& op, bool store)
   float minv = op.GetMinV();
   float maxv = op.GetMaxV();
   for(VMap::const_iterator it=vmap_.begin();it!=vmap_.end();++it) {
-    va_.SetColor(it->second,impl::MappedProperty(mh,prop,g,minv,maxv,sh_.GetVertex(it->first).position));
+	va_.SetColor(it->second,impl::MappedProperty(mh,prop,g,minv,maxv,sh_.GetVertex(it->first).position));
   }
   FlagRefresh();
 }
 #endif //OST_IMG_ENABLED
 
-void Surface::CleanColorOps()
-{
+void Surface::CleanColorOps(){
   GfxObj::CleanColorOps();
 }
 
-void Surface::ReapplyColorOps()
-{
+void Surface::ReapplyColorOps(){
   GfxObj::ReapplyColorOps();
 }
 
diff --git a/modules/gfx/src/vertex_array.cc b/modules/gfx/src/vertex_array.cc
index 06d9123ee..970c09887 100644
--- a/modules/gfx/src/vertex_array.cc
+++ b/modules/gfx/src/vertex_array.cc
@@ -77,7 +77,7 @@ IndexedVertexArray::Entry::Entry(const Vec3& vv, const Vec3& nn, const Color& cc
 IndexedVertexArray::IndexedVertexArray()
 {
   initialized_=false;
-  Reset(); // replaces ctor initialization list
+  Clear(); // replaces ctor initialization list
 }
 
 IndexedVertexArray::~IndexedVertexArray()
@@ -249,7 +249,7 @@ void IndexedVertexArray::AddIcoSphere(const SpherePrim& prim, unsigned int detai
   }
 }
 
-void IndexedVertexArray::AddCylinder(const CylinderPrim& prim, unsigned int detail,bool cap)
+void IndexedVertexArray::AddCylinder(const CylinderPrim& prim, unsigned int detail)
 {
   dirty_=true;
   ambient_dirty_=true;
@@ -259,54 +259,33 @@ void IndexedVertexArray::AddCylinder(const CylinderPrim& prim, unsigned int deta
   const std::vector<Vec3>& vlist = detail::GetPrebuildCyl(level);
   
   Vec3 off(0.0,0.0,prim.length);
-
-  Vec3 cn0 = cap ? prim.rotmat* geom::Vec3(0.0,0.0,-1.0) : Vec3();
-  Vec3 cn1 = -cn0;
-  VertexID cid0 = cap ? Add(prim.start, cn0 , prim.color1) : 0;
-  VertexID cid7 = cap ? Add(prim.rotmat * off + prim.start, cn1, prim.color2) : 0;
   
   // prepare first vertices to add
   std::vector<Vec3>::const_iterator it=vlist.begin();
   Vec3 v0 = (*it);
   Vec3 n0 = prim.rotmat * v0; 
   v0*=prim.radius;
-  VertexID id1 = Add(prim.rotmat * v0 + prim.start, n0, prim.color1);
-  VertexID id2 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color2);
-  VertexID cid1 = cap ? Add(prim.rotmat * v0 + prim.start, cn0, prim.color1) : 0;
-  VertexID cid2 = cap ? Add(prim.rotmat * (v0+off) + prim.start, cn1, prim.color2) : 0;
+  VertexID id1 = Add(prim.rotmat * v0 + prim.start, n0, prim.color);
+  VertexID id2 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color);
   
   // now for the loop around the circle
   VertexID id3=id1;
   VertexID id4=id2;
-  VertexID cid3=cid1;
-  VertexID cid4=cid2;
   ++it;
   for(;it!=vlist.end();++it) {
     v0 = (*it);
     n0 = prim.rotmat * v0; 
     v0 *= prim.radius;
-    VertexID id5 = Add(prim.rotmat * v0 + prim.start, n0, prim.color1);
-    VertexID id6 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color2);
+    VertexID id5 = Add(prim.rotmat * v0 + prim.start, n0, prim.color);
+    VertexID id6 = Add(prim.rotmat * (v0+off) + prim.start, n0, prim.color);
     AddTri(id3,id5,id4);
     AddTri(id5,id6,id4);
-    if(cap) {
-      VertexID cid5 = Add(prim.rotmat * v0 + prim.start, cn0, prim.color1);
-      VertexID cid6 = Add(prim.rotmat * (v0+off) + prim.start, cn1, prim.color2);
-      AddTri(cid0,cid5,cid3);
-      AddTri(cid7,cid4,cid6);
-      cid3=cid5;
-      cid4=cid6;
-    }
     id3=id5;
     id4=id6;
   }
   // and finally close the circle
   AddTri(id3,id1,id4);
   AddTri(id1,id2,id4);
-  if(cap) {
-    AddTri(cid0,cid1,cid3);
-    AddTri(cid7,cid4,cid2);
-  }
 }
 
 Vec3 IndexedVertexArray::GetVert(VertexID id) const
@@ -368,9 +347,7 @@ void IndexedVertexArray::RenderGL()
   if(!initialized_) {
     LOGN_DUMP("initializing vertex array lists");
 #if OST_SHADER_SUPPORT_ENABLED
-    if(!Scene::Instance().InOffscreenMode()) {
-      glGenBuffers(7,buffer_id_);
-    }
+    glGenBuffers(7,buffer_id_);
 #endif
     outline_mat_dlist_=glGenLists(1);
     initialized_=true;
@@ -392,7 +369,6 @@ 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 {
@@ -468,11 +444,6 @@ void IndexedVertexArray::RenderGL()
 #if OST_SHADER_SUPPORT_ENABLED
     if(use_ambient_ && !ambient_data_.empty()) {
       glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"occlusion_flag"),1);
-      glUniform2f(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"ambient_weight"),
-                  local_ambient_weight_,
-                  ambient_occlusion_weight_);
-    } else {
-      glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"occlusion_flag"),0);
     }
 #endif
   }
@@ -540,6 +511,12 @@ void IndexedVertexArray::RenderGL()
     }
   }
 
+#if OST_SHADER_SUPPORT_ENABLED
+  if(use_ambient_) {
+    glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"occlusion_flag"),0);
+  }
+#endif
+
   if(draw_normals_) {
     //glColor3f(1,0,0);
     glBegin(GL_LINES);
@@ -562,16 +539,13 @@ void IndexedVertexArray::RenderGL()
 namespace {
   unsigned int col_to_index(float* c)
   {
-    // don't look too closely - I am lacking sufficient caffeine to do this more elegantly
-    int ret= std::max(0,std::min<int>(511,static_cast<int>(round(c[0]*7.0f))*64+static_cast<int>(round(c[1]*7.0f))*8+static_cast<unsigned int>(round(c[2]*7.0f))));
-    return static_cast<unsigned int>(ret);
+    return static_cast<unsigned int>(c[0]*7.0)*64+static_cast<unsigned int>(c[1]*7.0)*8+static_cast<unsigned int>(c[2]*7.0);
   }
 }
 
 void IndexedVertexArray::RenderPov(PovState& pov, const std::string& name)
 {
   if(entry_list_.empty()) return;
-
   pov.inc() << "mesh2 {\n";
 
   pov.inc() << " vertex_vectors { " << entry_list_.size() << ",\n";
@@ -633,7 +607,7 @@ void IndexedVertexArray::RenderPov(PovState& pov, const std::string& name)
   pov.inc() << "}\n";
 }
 
-void IndexedVertexArray::Clear()
+void IndexedVertexArray::Clear() 
 {
   dirty_=true;
   ambient_dirty_=true;
@@ -642,13 +616,6 @@ void IndexedVertexArray::Clear()
   tri_index_list_.clear();
   line_index_list_.clear();
   ntentry_list_.clear();
-  ambient_data_.clear();
-  use_ambient_=false;
-} 
-
-void IndexedVertexArray::Reset() 
-{
-  Clear();
   mode_=0x4;
   poly_mode_=2;
   lighting_=true;
@@ -666,8 +633,8 @@ void IndexedVertexArray::Reset()
   outline_exp_factor_=0.1;
   outline_exp_color_=Color(0,0,0);
   draw_normals_=false;
-  local_ambient_weight_=0.3;
-  ambient_occlusion_weight_=1.0;
+  use_ambient_=false;
+  ambient_data_.clear();
 }
 
 void IndexedVertexArray::FlagRefresh()
@@ -1095,13 +1062,10 @@ void IndexedVertexArray::copy(const IndexedVertexArray& va)
   draw_normals_=va.draw_normals_;
   use_ambient_=va.use_ambient_;
   ambient_data_=va.ambient_data_;
-  local_ambient_weight_=va.local_ambient_weight_;
-  ambient_occlusion_weight_=va.ambient_occlusion_weight_;
 }
   
 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/gfx/src/vertex_array.hh b/modules/gfx/src/vertex_array.hh
index 3279eafad..eed4d2a7f 100644
--- a/modules/gfx/src/vertex_array.hh
+++ b/modules/gfx/src/vertex_array.hh
@@ -134,7 +134,7 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   // add an icosahedral based sphere with the given params to the va
   void AddIcoSphere(const SpherePrim& prim, unsigned int detail);
 
-  void AddCylinder(const CylinderPrim& prim, unsigned int detail,bool cap=false);
+  void AddCylinder(const CylinderPrim& prim, unsigned int detail);
 
   geom::Vec3 GetVert(VertexID id) const;
   void SetVert(VertexID id, const geom::Vec3& vert);
@@ -151,33 +151,13 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   // POVray export
   void RenderPov(PovState& pov, const std::string& name);
 
-  // turn on ambient lighting, first call may take a while
-  void UseAmbient(bool f);
-
-  // see fraglight_lf_fs shader
-  void AmbientLocalWeight(float w) {local_ambient_weight_=w;}
-  // see fraglight_lf_fs shader
-  void AmbientOcclusionWeight(float w) {ambient_occlusion_weight_=w;}
-
-  Color GetAmbientColor(VertexID id) const;
-  void SetAmbientColor(VertexID id, const Color& col);
-
-  // only removes the drawing elements
+  
   void Clear();
-  // removes all elements and resets internal state to default
-  void Reset();
-
-  // forces re-calculation of some buffered features
   void FlagRefresh();
 
-  // for debugging, draw all normals
+  void CalcNormals(float smoothf);
   void DrawNormals(bool f);
 
-  // NOTE: all methods below could be delegated to the outside, 
-  // using the GetEntries() and Get*Indices() member functions
-
-  // experimental, do not use
-  void CalcNormals(float smoothf);
   // experimental, do not use
   void CalcFullNormals();
   // experimental, do not use
@@ -186,13 +166,17 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   void NPatch();
   // experimental, do not use
   void SmoothVertices(float smoothf);
-
+  // experimental, do not use
+  void UseAmbient(bool f);
 
   const EntryList& GetEntries() const {return entry_list_;}
   const IndexList& GetQuadIndices() const {return quad_index_list_;}
   const IndexList& GetTriIndices() const {return tri_index_list_;}
   const IndexList& GetLineIndices() const {return line_index_list_;}
 
+  Color GetAmbientColor(VertexID id) const;
+  void SetAmbientColor(VertexID id, const Color& col);
+  
  private:
   bool initialized_;
   
@@ -230,8 +214,6 @@ class DLLEXPORT_OST_GFX IndexedVertexArray {
   bool use_ambient_;
   bool ambient_dirty_;
   std::vector<float> ambient_data_;
-  float local_ambient_weight_;
-  float ambient_occlusion_weight_;
 
   void copy(const IndexedVertexArray& va);
   bool prep_buff();
diff --git a/modules/gui/pymod/scene/cpk_widget.py b/modules/gui/pymod/scene/cpk_widget.py
index 7df408743..5f6c7de3c 100644
--- a/modules/gui/pymod/scene/cpk_widget.py
+++ b/modules/gui/pymod/scene/cpk_widget.py
@@ -42,45 +42,28 @@ class CPKWidget(RenderModeWidget):
     
     self.sphere_spinbox_ = QtGui.QSpinBox()
     self.sphere_spinbox_.setRange(min_sphere_detail, max_sphere_detail)
-
-    cpk_mode_label = QtGui.QLabel("Rendering Mode")
-    self.cpk_mode_ = QtGui.QComboBox()
-    self.cpk_mode_.addItem("Triangles")
-    self.cpk_mode_.addItem("Fast Spheres (exp")
-    self.cpk_mode_.addItem("Fast Spheres ++ (exp)")
-
+    
     cpk_label = QtGui.QLabel(self.text_)
     font = cpk_label.font()
     font.setBold(True)
     
     sphere_label = QtGui.QLabel("Sphere Detail")
     grid = QtGui.QGridLayout()
-    row=0
-    grid.addWidget(cpk_label,row,0,1,1)
-    row+=1
-    grid.addWidget(sphere_label, row, 0, 1, 3)
-    grid.addWidget(self.sphere_spinbox_, row, 2, 1, 1)
-    row+=1
-    grid.addWidget(cpk_mode_label,row,0,1,1)
-    grid.addWidget(self.cpk_mode_,row,3,1,2)
-    row+=1
-    grid.setRowStretch(row,1)
+    grid.addWidget(cpk_label,0,0,1,1)
+    grid.addWidget(sphere_label, 1, 0, 1, 3)
+    grid.addWidget(self.sphere_spinbox_, 1, 2, 1, 1)
+    grid.setRowStretch(2,1)
     self.setLayout(grid)
   
     QtCore.QObject.connect(self.sphere_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSphereDetail)
-    QtCore.QObject.connect(self.cpk_mode_, QtCore.SIGNAL("currentIndexChanged(int)"), self.UpdateCPKMode)
     
     self.setMinimumSize(250,60)
     
   def UpdateSphereDetail(self, value):
     self.GetOptions().SetSphereDetail(value)
-
-  def UpdateCPKMode(self, value):
-    self.GetOptions().SetCPKMode(value)
     
   def UpdateGui(self,options):
     self.sphere_spinbox_.setValue(options.GetSphereDetail())
-    self.cpk_mode_.setCurrentIndex(options.GetCPKMode())
 
   def GetText(self):
     return self.text_
diff --git a/modules/gui/pymod/scene/hsc_widget.py b/modules/gui/pymod/scene/hsc_widget.py
index dd63750b0..b5f716a0a 100644
--- a/modules/gui/pymod/scene/hsc_widget.py
+++ b/modules/gui/pymod/scene/hsc_widget.py
@@ -23,7 +23,7 @@ from ost import gfx
 from PyQt4 import QtCore, QtGui
 from render_mode_widget import RenderModeWidget
 
-# HSC Render Options
+#Tube Render Options
 class HSCWidget(RenderModeWidget):
   def __init__(self, parent=None):
     RenderModeWidget.__init__(self, parent)
@@ -55,7 +55,7 @@ class HSCWidget(RenderModeWidget):
 
     min_profile=0
     max_profile=4
-
+    
     #########UI##########
     
     #Poly Mode
@@ -119,41 +119,48 @@ class HSCWidget(RenderModeWidget):
     font = helix_label.font()
     font.setBold(True)
     
-    helix_mode_label = QtGui.QLabel("Helix Mode")
-    self.helix_mode_cb_ = QtGui.QComboBox()
-    self.helix_mode_cb_.addItem("Spiral")
-    self.helix_mode_cb_.addItem("Cylinder")
-
+    #Helix Radius
     radius_helix_label = QtGui.QLabel("Width")
+    
     self.width_helix_spinbox_ = QtGui.QDoubleSpinBox()
     self.width_helix_spinbox_.setRange(min_width, max_width)
     self.width_helix_spinbox_.setDecimals(1)
     self.width_helix_spinbox_.setSingleStep(0.1)
+    
     self.width_helix_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self)
     self.width_helix_slider_.setRange(min_width*10.0, max_width*10.0)
     self.width_helix_slider_.setTickPosition(QtGui.QSlider.NoTicks)
     self.width_helix_slider_.setTickInterval(1)
     
+    
+    #Helix Ratio
     ratio_helix_label = QtGui.QLabel("Thickness")
+    
     self.thickness_helix_spinbox_ = QtGui.QDoubleSpinBox()
     self.thickness_helix_spinbox_.setRange(min_ratio,max_ratio)
     self.thickness_helix_spinbox_.setDecimals(1)
     self.thickness_helix_spinbox_.setSingleStep(0.1)
+    
     self.thickness_helix_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self)
     self.thickness_helix_slider_.setRange(min_ratio*10.0,max_ratio*10.0)
     self.thickness_helix_slider_.setTickPosition(QtGui.QSlider.NoTicks)
     self.thickness_helix_slider_.setTickInterval(1)
     
+    
+    #Helix ECC
     ecc_helix_label = QtGui.QLabel("ECC")
+    
     self.ecc_helix_spinbox_ = QtGui.QDoubleSpinBox()
     self.ecc_helix_spinbox_.setRange(min_ecc,max_ecc)
     self.ecc_helix_spinbox_.setDecimals(1)
     self.ecc_helix_spinbox_.setSingleStep(0.1)
+    
     self.ecc_helix_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self)
     self.ecc_helix_slider_.setRange(min_ecc*10,max_ecc*10)
     self.ecc_helix_slider_.setTickPosition(QtGui.QSlider.NoTicks)
     self.ecc_helix_slider_.setTickInterval(1)
     
+    # Helix Profile Type
     helix_profile_label = QtGui.QLabel("Helix Profile Type")
     self.helix_profile_spinbox_ = QtGui.QSpinBox()
     self.helix_profile_spinbox_.setRange(min_profile, max_profile)
@@ -163,47 +170,52 @@ class HSCWidget(RenderModeWidget):
     font = strand_label.font()
     font.setBold(1)
     
-    strand_mode_label = QtGui.QLabel("Strand Mode")
-    self.strand_mode_cb_ = QtGui.QComboBox()
-    self.strand_mode_cb_.addItem("Curved")
-    self.strand_mode_cb_.addItem("Straight")
-
+    #Strand Radius
     radius_strand_label = QtGui.QLabel("Width")
+    
     self.width_strand_spinbox_ = QtGui.QDoubleSpinBox()
     self.width_strand_spinbox_.setRange(min_width, max_width)
     self.width_strand_spinbox_.setDecimals(1)
     self.width_strand_spinbox_.setSingleStep(0.1)
+    
     self.width_strand_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self)
     self.width_strand_slider_.setRange(min_width*10, max_width*10)
     self.width_strand_slider_.setTickPosition(QtGui.QSlider.NoTicks)
     self.width_strand_slider_.setTickInterval(1)
     
-
+    
+    #Strand Ratio
     ratio_strand_label = QtGui.QLabel("Thickness")
+    
     self.thickness_strand_spinbox_ = QtGui.QDoubleSpinBox()
     self.thickness_strand_spinbox_.setRange(min_ratio,max_ratio)
     self.thickness_strand_spinbox_.setDecimals(1)
     self.thickness_strand_spinbox_.setSingleStep(0.1)
+    
     self.thickness_strand_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self)
     self.thickness_strand_slider_.setRange(min_ratio*10,max_ratio*10)
     self.thickness_strand_slider_.setTickPosition(QtGui.QSlider.NoTicks)
     self.thickness_strand_slider_.setTickInterval(1)
     
+    
+    #Strand ECC
     ecc_strand_label = QtGui.QLabel("ECC")
+    
     self.ecc_strand_spinbox_ = QtGui.QDoubleSpinBox()
     self.ecc_strand_spinbox_.setRange(min_ecc,max_ecc)
     self.ecc_strand_spinbox_.setDecimals(1)
     self.ecc_strand_spinbox_.setSingleStep(0.1)
+    
     self.ecc_strand_slider_ = QtGui.QSlider(QtCore.Qt.Horizontal, self)
     self.ecc_strand_slider_.setRange(min_ecc*10,max_ecc*10)
     self.ecc_strand_slider_.setTickPosition(QtGui.QSlider.NoTicks)
     self.ecc_strand_slider_.setTickInterval(1)  
     
+    # Strand Profile Type
     strand_profile_label = QtGui.QLabel("Strand Profile Type")
     self.strand_profile_spinbox_ = QtGui.QSpinBox()
     self.strand_profile_spinbox_.setRange(min_profile, max_profile)
 
-    # layout
     row=1
     grid = QtGui.QGridLayout()
     grid.addWidget(poly_mode_label,row,0,1,1)
@@ -230,9 +242,6 @@ class HSCWidget(RenderModeWidget):
     row+=1
     grid.addWidget(helix_label, row, 0, 1, 3)
     row+=1
-    grid.addWidget(helix_mode_label,row,0,1,1)
-    grid.addWidget(self.helix_mode_cb_,row,3,1,2)
-    row+=1
     grid.addWidget(radius_helix_label, row, 0, 1, 1)
     grid.addWidget(self.width_helix_slider_, row, 1, 1, 3)
     grid.addWidget(self.width_helix_spinbox_, row, 4, 1, 1)
@@ -250,9 +259,6 @@ class HSCWidget(RenderModeWidget):
     row+=1
     grid.addWidget(strand_label, row, 0, 1, 3)
     row+=1
-    grid.addWidget(strand_mode_label,row,0,1,1)
-    grid.addWidget(self.strand_mode_cb_,row,3,1,2)
-    row+=1
     grid.addWidget(radius_strand_label, row, 0, 1, 1)
     grid.addWidget(self.width_strand_slider_, row, 1, 1, 3)
     grid.addWidget(self.width_strand_spinbox_, row, 4, 1, 1)
@@ -270,8 +276,7 @@ class HSCWidget(RenderModeWidget):
     
     grid.setRowStretch(row+1,1)
     self.setLayout(grid)
-
-    # signals
+    
     QtCore.QObject.connect(self.spline_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSplineDetail)
     QtCore.QObject.connect(self.arc_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateArcDetail)
     QtCore.QObject.connect(self.poly_mode_cb_, QtCore.SIGNAL("currentIndexChanged(int)"), self.UpdatePolyMode)
@@ -282,7 +287,6 @@ class HSCWidget(RenderModeWidget):
     QtCore.QObject.connect(self.thickness_tube_slider_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSliderTubeRatio)
     QtCore.QObject.connect(self.tube_profile_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateTubeProfileType)
     
-    QtCore.QObject.connect(self.helix_mode_cb_, QtCore.SIGNAL("currentIndexChanged(int)"), self.UpdateHelixMode)
     QtCore.QObject.connect(self.width_helix_spinbox_, QtCore.SIGNAL("valueChanged(double)"), self.UpdateHelixWidth)
     QtCore.QObject.connect(self.width_helix_slider_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSliderHelixWidth)
     QtCore.QObject.connect(self.thickness_helix_spinbox_, QtCore.SIGNAL("valueChanged(double)"), self.UpdateHelixThickness)
@@ -291,7 +295,6 @@ class HSCWidget(RenderModeWidget):
     QtCore.QObject.connect(self.ecc_helix_slider_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSliderHelixEcc)
     QtCore.QObject.connect(self.helix_profile_spinbox_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateHelixProfileType)
 
-    QtCore.QObject.connect(self.strand_mode_cb_, QtCore.SIGNAL("currentIndexChanged(int)"), self.UpdateStrandMode)
     QtCore.QObject.connect(self.width_strand_spinbox_, QtCore.SIGNAL("valueChanged(double)"), self.UpdateStrandWidth)
     QtCore.QObject.connect(self.width_strand_slider_, QtCore.SIGNAL("valueChanged(int)"), self.UpdateSliderStrandWidth)
     QtCore.QObject.connect(self.thickness_strand_spinbox_, QtCore.SIGNAL("valueChanged(double)"), self.UpdateStrandThickness)
@@ -311,14 +314,10 @@ class HSCWidget(RenderModeWidget):
     self.UpdateTubeRadiusGui(options.GetTubeRadius())
     self.UpdateTubeRatioGui(options.GetTubeRatio())
     self.tube_profile_spinbox_.setValue(options.GetTubeProfileType())
-
-    self.helix_mode_cb_.setCurrentIndex(options.GetHelixMode())
     self.UpdateHelixWidthGui(options.GetHelixWidth())
     self.UpdateHelixThicknessGui(options.GetHelixThickness())
     self.UpdateHelixEccGui(options.GetHelixEcc())
     self.helix_profile_spinbox_.setValue(options.GetHelixProfileType())
-
-    self.strand_mode_cb_.setCurrentIndex(options.GetStrandMode())
     self.UpdateStrandWidthGui(options.GetStrandWidth())
     self.UpdateStrandThicknessGui(options.GetStrandThickness())
     self.UpdateStrandEccGui(options.GetStrandEcc())
@@ -348,9 +347,6 @@ class HSCWidget(RenderModeWidget):
   def UpdateTubeProfileType(self, value):
     self.GetOptions().SetTubeProfileType(value)
     
-  def UpdateHelixMode(self, value):
-    self.GetOptions().SetHelixMode(value)
-    
   def UpdateHelixWidth(self, value):
     self.GetOptions().SetHelixWidth(value) 
     
@@ -372,9 +368,6 @@ class HSCWidget(RenderModeWidget):
   def UpdateSliderHelixEcc(self, value):
     self.GetOptions().SetHelixEcc(value/10.0)
     
-  def UpdateStrandMode(self, value):
-    self.GetOptions().SetStrandMode(value)
-    
   def UpdateStrandWidth(self, value):
     self.GetOptions().SetStrandWidth(value)
 
-- 
GitLab