Index: /cpp/frams/Makefile-GDK
===================================================================
--- /cpp/frams/Makefile-GDK	(revision 268)
+++ /cpp/frams/Makefile-GDK	(revision 269)
@@ -5,10 +5,10 @@
 include frams/Makefile-GDK-files
 
-GDK_TESTS=genoconv_test gdk_test geno_test genooper_test genooper_test_fTest neuro_test loader_test serial_test multiline_f0_test f0_variants_test full_props part_shapes neuro_layout_test geometry_apices_test geometry_info_test geometry_surface_test geometry_volume_test
+GDK_TESTS=genoconv_test gdk_test geno_test genooper_test genooper_test_fTest neuro_test loader_test serial_test multiline_f0_test f0_variants_test full_props shapeconvert part_shapes neuro_layout_test geometry_apices_test geometry_info_test geometry_surface_test geometry_volume_test
 
 gdk_tests: $(GDK_TESTS)
 
 GDK_BUILD_CONFIG= -include frams/config/gdk_build_config.h
-CXXFLAGS= -I$(CURDIR) -DLINUX $(GDK_BUILD_CONFIG) -Wno-parentheses -Wno-overloaded-virtual -Wno-format -g
+CXXFLAGS= -I$(CURDIR) -std=gnu++11 -DLINUX $(GDK_BUILD_CONFIG) -Wno-parentheses -Wno-overloaded-virtual -Wno-format -g
 
 #############################################
@@ -47,4 +47,7 @@
 	$(CXX) $(FULL_PROPS_OBJS) $(LDFLAGS) -o $@
 
+shapeconvert: $(SHAPECONVERT_OBJS)
+	$(CXX) $(SHAPECONVERT_OBJS) $(LDFLAGS) -o $@
+
 part_shapes: $(PART_SHAPES_OBJS)
 	$(CXX) $(PART_SHAPES_OBJS) $(LDFLAGS) -o $@
Index: /cpp/frams/Makefile-GDK-files
===================================================================
--- /cpp/frams/Makefile-GDK-files	(revision 268)
+++ /cpp/frams/Makefile-GDK-files	(revision 269)
@@ -47,4 +47,6 @@
 FULL_PROPS_OBJS= frams/_demos/full_props.o frams/errmgr/stdouterr.o frams/virtfile/virtfile.o  frams/virtfile/stdiofile.o $(GDK_OBJS) $(GENOCONV_GDK_OBJS) $(GENMAN_GDK_OBJS)
 
+SHAPECONVERT_OBJS= frams/_demos/shapeconvert.o frams/errmgr/stdouterr.o frams/virtfile/virtfile.o  frams/virtfile/stdiofile.o $(GDK_OBJS) $(GENOCONV_GDK_OBJS) $(GENMAN_GDK_OBJS)
+
 SERIAL_TEST_OBJS= frams/_demos/serial_test.o frams/virtfile/virtfile.o  $(GDK_OBJS) $(GENOCONV_GDK_OBJS)
 
Index: /cpp/frams/_demos/shapeconvert.cpp
===================================================================
--- /cpp/frams/_demos/shapeconvert.cpp	(revision 269)
+++ /cpp/frams/_demos/shapeconvert.cpp	(revision 269)
@@ -0,0 +1,94 @@
+// This file is a part of the Framsticks GDK.
+// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
+// Refer to http://www.framsticks.com/ for further information.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <frams/virtfile/stdiofile.h>
+
+#include <frams/model/model.h>
+#include <frams/errmgr/stdouterr.h>
+#include <frams/genetics/preconfigured.h>
+
+/**
+ @file
+ Sample code: Convert old-style shapes (sticks are Joints) to new style (sticks are Parts)
+ Usage: shapeconvert [-sSHAPE] [-tTHICKNESS] [genotype_or_stdin]
+
+ Calling examples:
+
+ # convert any genotype to f0 using new-style shapes:
+ shapeconvert "X"
+
+ //0
+ m:
+ p:0.5, sh=3, sx=0.5, sy=0.200000002980232, sz=0.200000002980232, rx=-1.5707963267949, rz=3.14159265358979
+
+ # load a genotype from file, convert to new shapes, display:
+ loader_test data/other.gen "Bird" | shapeconvert -s1 - | theater.exe -g -
+
+ */
+
+int main(int argc, char*argv[])
+{
+	StdioFILE::setStdio();//setup VirtFILE::Vstdin/out/err
+	StdoutErrorHandler err(ErrorHandlerBase::DontBlock, VirtFILE::Vstderr); //errors -> stderr, don't interfere with stdout
+
+	PreconfiguredGenetics genetics;
+	Part::Shape shape = Part::SHAPE_CYLINDER;
+	float thickness = 0.2;
+
+	char* gen_arg = 0;
+	for (int i = 1; i < argc; i++)
+	{
+		char* ar = argv[i];
+		if (ar[0] == '-')
+			switch (ar[1])
+		{
+			case 's': shape = (Part::Shape)atol(ar + 2);
+				if ((shape != Part::SHAPE_ELLIPSOID) && (shape != Part::SHAPE_CUBOID) && (shape != Part::SHAPE_CYLINDER))
+				{
+					FMprintf("", "shapeconvert", FMLV_ERROR, "Invalid shape");
+					return 4;
+				}
+				break;
+			case 't': thickness = atof(ar + 2); break;
+			case 'h': puts("Usage: shapeconvert [-sSHAPE] [-tTHICKNESS] [genotype_or_stdin]\n\tSHAPE: 1=ellipsoid, 2=cuboid, 3(default)=cylinder\n\tTHICKNESS: used for Part.sy/sz (default=0.2)"); break;
+		}
+		else
+			if (!gen_arg)
+				gen_arg = ar;
+	}
+	SString gen;
+	if (gen_arg)
+		gen = gen_arg;
+	else
+		loadSString(VirtFILE::Vstdin, gen);
+	Geno g(gen);
+	Model m(g);
+
+	if (!m.isValid())
+	{
+		FMprintf("", "shapeconvert", FMLV_ERROR, "Cannot build Model from the supplied genotype");
+		return 2;
+	}
+
+	if (m.getShape() != Model::SHAPE_OLD)
+	{
+		FMprintf("", "shapeconvert", FMLV_ERROR, "Only old style shapes can be converted");
+		return 3;
+	}
+
+	Model newmodel;
+	newmodel.open();
+	newmodel.buildUsingNewShapes(m, shape, thickness);
+	newmodel.close();
+
+	// Normal f0 would be retrieved using m.getF0Geno().
+	// The following form allows for more control:
+	Geno f0_g = newmodel.getF0Geno();
+	puts((const char*)f0_g.toString());
+
+	return 0;
+}
Index: /cpp/frams/model/model.cpp
===================================================================
--- /cpp/frams/model/model.cpp	(revision 268)
+++ /cpp/frams/model/model.cpp	(revision 269)
@@ -29,4 +29,5 @@
 f0map=0;
 f0genoknown=1;
+shape=SHAPE_UNKNOWN;
 }
 
@@ -874,4 +875,5 @@
 int i,k;
 int ret=1;
+shape=SHAPE_UNKNOWN;
 if ((parts.size()==0)&&(neurons.size()==0)) return 0;
 if (parts.size()==0)
@@ -903,4 +905,14 @@
 	if (p->p.y+p->size > bbmax.y) bbmax.y=p->p.y+p->size;
 	if (p->p.z+p->size > bbmax.z) bbmax.z=p->p.z+p->size;
+	if (shape==SHAPE_UNKNOWN)
+		shape=(p->shape==Part::SHAPE_DEFAULT)?SHAPE_OLD:SHAPE_NEW;
+	else if (shape!=SHAPE_ILLEGAL)
+		{
+		if ((p->shape==Part::SHAPE_DEFAULT) ^ (shape==SHAPE_OLD))
+			{
+			shape=SHAPE_ILLEGAL;
+			FMprintf("Model","internalCheck",FMLV_WARN,"Inconsistent part shapes (mixed old and new shapes)");
+			}
+		}
 	}
 size=bbmax-bbmin;
@@ -983,4 +995,12 @@
 			 i,(const char*)geno.getName());
 		ret=0;
+		}
+	if (shape!=SHAPE_ILLEGAL)
+		{
+		if ((j->shape==Joint::SHAPE_DEFAULT) ^ (shape==SHAPE_OLD))
+			{
+			shape==SHAPE_ILLEGAL;
+			FMprintf("Model","internalCheck",FMLV_WARN,"Inconsistent joint shapes (mixed old and new shapes)");
+			}
 		}
 	}
@@ -1082,4 +1102,6 @@
 		}
 	}
+if (shape==SHAPE_ILLEGAL)
+	ret=0;
 return ret;
 }
@@ -1258,4 +1280,40 @@
 	tmpp-=j->part1->p;
 	j->d=j->part2->o.revTransform(tmpp);
+	}
+}
+
+void Model::buildUsingNewShapes(const Model& old, Part::Shape default_shape, float thickness)
+{
+for(int i=0;i<old.getJointCount();i++)
+	{
+	Joint *oj=old.getJoint(i);
+	Part *p = addNewPart(default_shape);
+	p->p=(oj->part1->p+oj->part2->p)/2;
+	Orient o;
+	o.lookAt(oj->part1->p-oj->part2->p);
+	p->rot=o.getAngles();
+	p->scale.x=oj->part1->p.distanceTo(oj->part2->p)/2;
+	p->scale.y = thickness;
+	p->scale.z = thickness;
+	}
+for(int i=0;i<old.getPartCount();i++)
+	{
+	Part *op=old.getPart(i);
+	for(int j=0;j<old.getJointCount();j++)
+		{
+		Joint *oj=old.getJoint(j);
+		if ((oj->part1==op)||(oj->part2==op))
+			{
+			for(int j2=j+1;j2<old.getJointCount();j2++)
+				{
+				Joint *oj2=old.getJoint(j2);
+				if ((oj2->part1==op)||(oj2->part2==op))
+					{
+					Joint *newj=addNewJoint(getPart(j),getPart(j2),Joint::SHAPE_SOLID);
+					}
+				}
+			break;
+			}
+		}
 	}
 }
Index: /cpp/frams/model/model.h
===================================================================
--- /cpp/frams/model/model.h	(revision 268)
+++ /cpp/frams/model/model.h	(revision 269)
@@ -117,4 +117,9 @@
 
 int checklevel;
+
+  public:
+enum Shape {SHAPE_UNKNOWN,SHAPE_ILLEGAL,SHAPE_OLD,SHAPE_NEW};
+  protected:
+Shape shape;
 
 void updateNeuroRefno(); // set Neuro::refno for all neurons
@@ -150,4 +155,5 @@
 int isValid() const {return buildstatus==valid;}
 int getErrorPosition(bool includingwarnings=false);
+Shape getShape() {return shape;}
 
 void updateRefno(); // set ::refno for all elements
@@ -387,4 +393,6 @@
 
 void disturb(double amount);
+
+void buildUsingNewShapes(const Model& src_old_shapes, Part::Shape default_shape = Part::SHAPE_CYLINDER, float thickness = 0.2);
 
 #ifdef EASYMAPDEBUG
Index: /cpp/frams/model/modelparts.h
===================================================================
--- /cpp/frams/model/modelparts.h	(revision 268)
+++ /cpp/frams/model/modelparts.h	(revision 269)
@@ -70,5 +70,5 @@
 static SString getDefaultStyle();
 Part(double _mass,double _size,double _density,double _friction,double _ingest,double _assim)
-	:PartBase(getDefaultStyle()),mass(_mass),size(_size),density(_density),friction(_friction),ingest(_ingest),assim(_assim)
+	  :PartBase(getDefaultStyle()),mass(_mass),size(_size),density(_density),friction(_friction),ingest(_ingest),assim(_assim)
 	{}
 void defassign();
@@ -86,5 +86,5 @@
 paInt shape;///default=old framsticks compatible, do not mix with shapes>0
 enum Shape {SHAPE_DEFAULT=0, SHAPE_ELLIPSOID=1, SHAPE_CUBOID=2, SHAPE_CYLINDER=3};
-double mass,size,density,friction,ingest,assim;
+double mass,size,density,friction,ingest,assim,hollow;
 Pt3D scale;
 Pt3D food;
