Index: OpenSceneGraph/trunk/src/osgPlugins/3dc/ReaderWriter3DC.cpp
===================================================================
--- OpenSceneGraph/trunk/src/osgPlugins/3dc/ReaderWriter3DC.cpp (revision 9343)
+++ OpenSceneGraph/trunk/src/osgPlugins/3dc/ReaderWriter3DC.cpp (revision 10010)
@@ -12,11 +12,77 @@
 #include <string.h>
 
-
-using namespace osg;
+class Writer3DCNodeVisitor: public osg::NodeVisitor {
+
+    public:
+        Writer3DCNodeVisitor(std::ostream& fout) :
+            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
+            _fout(fout)
+        {
+           // _fout << "# file written by OpenSceneGraph" << std::endl << std::endl;
+        }
+
+        virtual void apply(osg::Geode &node);
+
+    protected:
+
+        Writer3DCNodeVisitor& operator = (const Writer3DCNodeVisitor&) { return *this; }
+        std::ostream& _fout;
+
+};
+
+void Writer3DCNodeVisitor::apply( osg::Geode &node )
+{
+    osg::Matrix matrix = osg::computeLocalToWorld(getNodePath());
+
+    unsigned int count = node.getNumDrawables();
+    for ( unsigned int i = 0; i < count; i++ )
+    {
+        osg::Geometry *geometry = node.getDrawable( i )->asGeometry();
+        if ( geometry )
+        {
+            osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
+            osg::Vec3Array* normals = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray());
+            osg::Vec3Array* colours = dynamic_cast<osg::Vec3Array*>(geometry->getColorArray());
+
+            if ( vertices ) {
+                for (unsigned int ii=0;ii<vertices->size();ii++) {
+
+                    // update nodes with world coords
+                    osg::Vec3d v = vertices->at(ii) * matrix;
+                    _fout << v[0] << ' ' << v[1] << ' ' << v[2];
+
+                    if ( colours )
+                    {
+                        v=colours->at(ii);
+                        _fout << ' ' << (int)v[0]*255.0 << ' ' << (int)v[1]*255.0 << ' ' << (int)v[2]*255.0;
+                    }
+                    else
+                    {
+                        _fout << " 255 255 255";
+                    }
+
+                    if ( normals )
+                    {
+                        v = normals->at(ii);
+                        _fout << ' ' << v[0] << ' ' << v[1] << ' ' << v[2];
+                    }
+                    else
+                    {
+                        _fout << " 0.0 0.0 1.0";
+                    }
+
+
+                    _fout << std::endl;
+                }
+            }
+
+        }
+    }
+}
 
 class ReaderWriter3DC : public osgDB::ReaderWriter
 {
     public:
-    
+
         ReaderWriter3DC()
         {
@@ -24,7 +90,7 @@
             supportsExtension("asc","3DC point cloud format");
         }
-    
+
         virtual const char* className() const { return "3DC point cloud reader"; }
-        
+
         virtual ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* options) const
         {
@@ -34,13 +100,26 @@
             std::string fileName = osgDB::findDataFile( file, options );
             if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
-            
+
             osg::notify(osg::INFO) << "Reading file "<<fileName<<std::endl;
-    
+
             const int LINE_SIZE = 1024;
             char line[LINE_SIZE];
-            
+
+            unsigned int targetNumVertices = 10000;
+
+            osg::Geode* geode = new osg::Geode;
+
+            osg::Geometry* geometry = new osg::Geometry;
+
+            osg::Vec3Array* vertices = new osg::Vec3Array;
+            osg::Vec3Array* normals = new osg::Vec3Array;
+            osg::Vec4ubArray* colours = new osg::Vec4ubArray;
+
+            osg::Vec3 pos;
+            osg::Vec3 normal(0.0,0.0,1.0);
+            int r=255,g=255,b=255,a=255;
+            char sep;
+
             osgDB::ifstream fin(fileName.c_str());
-            
-            unsigned int num = 0;
             while (fin)
             {
@@ -51,55 +130,14 @@
                     osg::notify(osg::INFO) <<"Comment: "<<line<<std::endl;
                 }
-                else
-                {
-                    ++num;
-                }
-            }
-            
-            
-            osg::notify(osg::INFO) << "num="<<num<<std::endl;
-            
-            unsigned int targetNumVertices = 10000;
-           
-    
-            osg::Geode* geode = new osg::Geode;
-
-            osg::Geometry* geometry = new osg::Geometry;
-            
-            osg::Vec3Array* vertices = new osg::Vec3Array;
-            osg::Vec3Array* normals = new osg::Vec3Array;
-            osg::Vec4ubArray* colours = new osg::Vec4ubArray;
-            
-            vertices->reserve(targetNumVertices);
-            normals->reserve(targetNumVertices);
-            colours->reserve(targetNumVertices);
-            
-            fin.close();
-            
-            osgDB::ifstream fin2(fileName.c_str());
-            while (fin2)
-            {
-                fin2.getline(line,LINE_SIZE);
-                if (line[0]=='#')
-                {
-                    // comment line
-                    osg::notify(osg::INFO) <<"Comment: "<<line<<std::endl;
-                }
                 else if (strlen(line)>0)
                 {
-                    ++num;
-                    
-                    osg::Vec3 pos,normal;
-                    int r,g,b;
-                    
-                    int a = sscanf(line,"%f %f %f %d %d %d %f %f %f",
-                                   &pos.x(),&pos.y(),&pos.z(),
-                                   &r,&g,&b,
-                                   &normal.x(),&normal.y(),&normal.z());
-                                
-                                
-                    if (a)
-                    {
-                    
+                    int matched = sscanf(line,"%f%c%f%c%f%c%d%c%d%c%d%c%f%c%f%c%f",
+                                   &pos.x(),&sep,&pos.y(),&sep,&pos.z(),&sep,
+                                   &r,&sep,&g,&sep,&b,&sep,
+                                   &normal.x(),&sep,&normal.y(),&sep,&normal.z());
+
+                    if (matched)
+                    {
+
                         if (vertices->size()>=targetNumVertices)
                         {
@@ -113,8 +151,8 @@
                             geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
                             geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS,0,vertices->size()));
-                            
+
                             geode->addDrawable(geometry);
 
-                            // allocate a new geometry                            
+                            // allocate a new geometry
                             geometry = new osg::Geometry;
 
@@ -128,12 +166,10 @@
 
                         }
-                                                        
+
                         vertices->push_back(pos);
                         normals->push_back(normal);
-                        colours->push_back(osg::Vec4ub(r,g,b,255));
-                        
+                        colours->push_back(osg::Vec4ub(r,g,b,a));
                     }
                 }
-                
             }
 
@@ -149,9 +185,23 @@
 
             geode->addDrawable(geometry);
-    
+
             return geode;
-    
-        }
-    
+
+        }
+
+        virtual WriteResult writeNode(const osg::Node& node,const std::string& fileName,const Options* options =NULL) const 
+        { 
+            if (!acceptsExtension(osgDB::getFileExtension(fileName)))
+                return WriteResult(WriteResult::FILE_NOT_HANDLED);
+
+            osgDB::ofstream f(fileName.c_str());
+
+            Writer3DCNodeVisitor nv(f); 
+
+            // we must cast away constness
+            (const_cast<osg::Node*>(&node))->accept(nv);
+
+            return WriteResult(WriteResult::FILE_SAVED); 
+        }
 };
 
