diff --git a/modules/gfx/pymod/__init__.py b/modules/gfx/pymod/__init__.py
index ec7f8e7983463874ea91ae1c6625661c08e6275f..7cb3cc51452eca9c2a1507b9e7b692e591ba2aa1 100644
--- a/modules/gfx/pymod/__init__.py
+++ b/modules/gfx/pymod/__init__.py
@@ -394,3 +394,16 @@ main_mod.scene.Stereo=Stereo
 import ost as ost_mod
 ost_mod.scene=Scene()
 ost_mod.scene.Stereo=Stereo
+
+def GostExporter(file,scale=1.0,to_origin=True):
+  e=GostExporter_(file)
+  e.scale=scale
+  e.to_origin=to_origin
+  return e
+
+def ColladaExporter(file,scale=1.0,to_origin=True):
+  e=ColladaExporter_(file)
+  e.scale=scale
+  e.to_origin=to_origin
+  return e
+
diff --git a/modules/gfx/pymod/export_exporter.cc b/modules/gfx/pymod/export_exporter.cc
index 655fe54f77282e2d6656142addf51e18006d7f7c..22c9a97432477c8f8c47b4ba6fd7d2cfac58451d 100644
--- a/modules/gfx/pymod/export_exporter.cc
+++ b/modules/gfx/pymod/export_exporter.cc
@@ -28,11 +28,16 @@ using namespace ost::gfx;
 
 void export_Exporter()
 {
-  class_<Exporter, boost::noncopyable>("Exporter", no_init);
+  class_<Exporter, boost::noncopyable>("Exporter", no_init)
+    .add_property("scale",&Exporter::GetScale,&Exporter::SetScale)
+    .add_property("to_origin",&Exporter::GetToOrigin,&Exporter::SetToOrigin)
+  ;
 
-  class_<GostExporter, bases<Exporter>, boost::noncopyable>("GostExporter", init<const std::string&>())
+  // internal class, factory function in __init__.py
+  class_<GostExporter, bases<Exporter>, boost::noncopyable>("GostExporter_", init<const std::string&>())
     ;
 
-  class_<ColladaExporter, bases<Exporter>, boost::noncopyable>("ColladaExporter", init<const std::string&, optional<float> >())
+  // internal class, factory function in __init__.py
+  class_<ColladaExporter, bases<Exporter>, boost::noncopyable>("ColladaExporter_", init<const std::string&>())
     ;
 }
diff --git a/modules/gfx/src/CMakeLists.txt b/modules/gfx/src/CMakeLists.txt
index f1671c0de0edb909ef11bf0c61cbebec2a4c61f2..bb60b35f1081586e5b3bbe65137b2e7a51dc181d 100644
--- a/modules/gfx/src/CMakeLists.txt
+++ b/modules/gfx/src/CMakeLists.txt
@@ -94,6 +94,7 @@ endif()
 
 set(OST_GFX_SOURCES
 bitmap_io.cc
+exporter.cc
 collada_exporter.cc
 color.cc
 primitives.cc
diff --git a/modules/gfx/src/collada_exporter.cc b/modules/gfx/src/collada_exporter.cc
index 902334f851fc0df651f58f380e3c3771e8ae1e96..d2b45c21e76db54c311f10ff1e8c7389049151b6 100644
--- a/modules/gfx/src/collada_exporter.cc
+++ b/modules/gfx/src/collada_exporter.cc
@@ -29,10 +29,10 @@
 
 namespace ost { namespace gfx {
 
-ColladaExporter::ColladaExporter(const std::string& file, float scale):
+ColladaExporter::ColladaExporter(const std::string& file):
+  Exporter(),
   file_(file),
   out_(file_.c_str()),
-  scale_(scale),
   obj_()
 {
   out_ << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
@@ -75,13 +75,23 @@ void ColladaExporter::SceneEnd(const Scene* scene)
   out_ << "   </node>\n";
 
   out_ << "   <node id=\"Root\" name=\"Root\">\n";
-  out_ << "    <matrix>\n";
-  geom::Mat4 tm=scene->GetTransform().GetMatrix();
-  out_ << "    " << tm(0,0) << " " << tm(0,1) << " " << tm(0,2) << " " << tm(0,3) << "\n";
-  out_ << "    " << tm(1,0) << " " << tm(1,1) << " " << tm(1,2) << " " << tm(1,3) << "\n";
-  out_ << "    " << tm(2,0) << " " << tm(2,1) << " " << tm(2,2) << " " << tm(2,3) << "\n";
-  out_ << "    " << tm(3,0) << " " << tm(3,1) << " " << tm(3,2) << " " << tm(3,3) << "\n";
-  out_ << "    </matrix>\n";
+  if(GetToOrigin()) {
+    out_ << "    <matrix>\n";
+    geom::Vec3 cen=scene->GetTransform().GetCenter();
+    out_ << "    1 0 0 " << -cen[0] << "\n";
+    out_ << "    0 1 0 " << -cen[1] << "\n";
+    out_ << "    0 0 1 " << -cen[2] << "\n";
+    out_ << "    0 0 0 1\n";
+    out_ << "    </matrix>\n";
+  } else {
+    out_ << "    <matrix>\n";
+    geom::Mat4 tm=scene->GetTransform().GetMatrix();
+    out_ << "    " << tm(0,0) << " " << tm(0,1) << " " << tm(0,2) << " " << tm(0,3) << "\n";
+    out_ << "    " << tm(1,0) << " " << tm(1,1) << " " << tm(1,2) << " " << tm(1,3) << "\n";
+    out_ << "    " << tm(2,0) << " " << tm(2,1) << " " << tm(2,2) << " " << tm(2,3) << "\n";
+    out_ << "    " << tm(3,0) << " " << tm(3,1) << " " << tm(3,2) << " " << tm(3,3) << "\n";
+    out_ << "    </matrix>\n";
+  }
   for(std::vector<std::string>::const_iterator oit=obj_.begin();oit!=obj_.end();++oit) {
     out_ << "    <node id=\"" << *oit << "\" name=\"" << *oit <<"\">\n";
     out_ << "     <instance_geometry url=\"#" << *oit << "\"/>\n";
@@ -126,10 +136,13 @@ void ColladaExporter::WriteVertexData(const float* vdata,
   out_ << "   <float_array count=\"" << count*3 << "\" id=\"" << name+"-Positions-array" << "\">\n";
   if(vdata) {
     const float* src=vdata;
+    float tmpv[3];
     for(unsigned int i=0;i<count;++i) {
-      out_ << scale_*src[0] << " ";
-      out_ << scale_*src[1] << " ";
-      out_ << scale_*src[2] << " ";
+      tmpv[0]=src[0]; tmpv[1]=src[1]; tmpv[2]=src[2];
+      TransformPosition(tmpv);
+      out_ << tmpv[0] << " ";
+      out_ << tmpv[1] << " ";
+      out_ << tmpv[2] << " ";
       src+=stride;
     }
   } else {
@@ -152,10 +165,13 @@ void ColladaExporter::WriteVertexData(const float* vdata,
   out_ << "   <float_array count=\"" << count*3 << "\" id=\"" << name+"-Normals-array" << "\">\n";
   if(ndata) {
     const float* src=ndata;
+    float tmpn[3];
     for(unsigned int i=0;i<count;++i) {
-      out_ << src[0] << " ";
-      out_ << src[1] << " ";
-      out_ << src[2] << " ";
+      tmpn[0]=src[0]; tmpn[1]=src[1]; tmpn[2]=src[2];
+      TransformNormal(tmpn);
+      out_ << tmpn[0] << " ";
+      out_ << tmpn[1] << " ";
+      out_ << tmpn[2] << " ";
       src+=stride;
     }
   } else {
diff --git a/modules/gfx/src/collada_exporter.hh b/modules/gfx/src/collada_exporter.hh
index c0192a10097e6cb0d2b48801431a3be2437509d5..7a05417c6826528bc49d956e33dc8109a3803a6d 100644
--- a/modules/gfx/src/collada_exporter.hh
+++ b/modules/gfx/src/collada_exporter.hh
@@ -35,7 +35,7 @@ namespace ost { namespace gfx {
 class DLLEXPORT_OST_GFX ColladaExporter: public Exporter
 {
 public:
-  ColladaExporter(const std::string& collada_file, float scale=1.0);
+  ColladaExporter(const std::string& collada_file);
   virtual ~ColladaExporter();
 
   // exporter interface
@@ -53,7 +53,6 @@ public:
 private:
   std::string file_;
   std::ofstream out_;
-  float scale_;
   std::vector<std::string> obj_;
 };
 
diff --git a/modules/gfx/src/exporter.hh b/modules/gfx/src/exporter.hh
index 20b0601aee6a110a4c713a687db50d4834c5978c..1780851eb94e5470f778ea648fed821782717f66 100644
--- a/modules/gfx/src/exporter.hh
+++ b/modules/gfx/src/exporter.hh
@@ -19,6 +19,11 @@
 #ifndef OST_GFX_EXPORTER_HH
 #define OST_GFX_EXPORTER_HH
 
+#include <ost/geom/vec3.hh>
+#include <ost/geom/vec4.hh>
+#include <ost/geom/mat3.hh>
+#include <ost/geom/mat4.hh>
+
 #include <ost/gfx/module_config.hh>
 
 namespace ost { namespace gfx {
@@ -34,6 +39,10 @@ public:
     OBJ=3
   };
 
+  Exporter() :
+    scale_(1.0),
+    to_origin_(true)
+  {}
   virtual ~Exporter() {}
   virtual void SceneStart(const Scene* scene) {}
   virtual void SceneEnd(const Scene* scene) {}
@@ -49,8 +58,32 @@ public:
   virtual void WriteLineData(const unsigned int* ij, size_t count) {}
   virtual void WriteTriData(const unsigned int* ijk, size_t count) {}
   virtual void WriteQuadData(const unsigned int* ijkl, size_t count) {}
+
+  // scale positions for absolute data formats (like dae)
+  void SetScale(float s) {scale_=s;}
+  float GetScale() const {return scale_;}
+  // if true (default), re-orient so that center is at (0,0,0)
+  // and viewing direction is along z
+  // (basically apply modelview matrix)
+  void SetToOrigin(bool b) {to_origin_=b;}
+  bool GetToOrigin() const {return to_origin_;}
+
+  // used by Scene::Export
+  void SetupTransform(const Scene* scene);
+  // used by WriteVertexData in derived classes
+  // modifies input arg!!
+  void TransformPosition(float* p) const;
+  void TransformNormal(float* n) const;
+
+private:
+  float scale_;
+  bool to_origin_;
+  geom::Mat4 vertex_tf_;
+  geom::Mat3 normal_tf_;
 };
 
+
+
 }} // ns
 
 #endif
diff --git a/modules/gfx/src/gost_exporter.cc b/modules/gfx/src/gost_exporter.cc
index 79a6e9b28390f1ce2d1890e88d824de48856e358..525a70aba0334a0dcdc1e0bfbbccee7ff28975e3 100644
--- a/modules/gfx/src/gost_exporter.cc
+++ b/modules/gfx/src/gost_exporter.cc
@@ -57,6 +57,7 @@ namespace ost { namespace gfx {
   }
 
 GostExporter::GostExporter(const std::string& fname):
+  Exporter(),
   file_(0)
 {
   file_=fopen(fname.c_str(),"w");
diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index ad86180aa623514451d426897a11e0fe4597431d..7ded8ad81e6465b92acaf2e371ac7f6ab8d8bad9 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -1784,6 +1784,7 @@ void Scene::ExportPov(const std::string& fname, const std::string& wdir)
 
 void Scene::Export(Exporter* ex) const
 {
+  ex->SetupTransform(this);
   ex->SceneStart(this);
   root_node_->Export(ex);
   ex->SceneEnd(this);