diff --git a/SimDynamics/DynamicsEngine/BulletEngine/BulletObject.cpp b/SimDynamics/DynamicsEngine/BulletEngine/BulletObject.cpp
index 53e66202d7fa874a6d41d14023cf8d80feb0bc97..41cd623299606278356805e5933c4afc57fc7d4c 100644
--- a/SimDynamics/DynamicsEngine/BulletEngine/BulletObject.cpp
+++ b/SimDynamics/DynamicsEngine/BulletEngine/BulletObject.cpp
@@ -11,11 +11,14 @@
 
 #include <BulletCollision/CollisionShapes/btShapeHull.h>
 #include <BulletCollision/CollisionShapes/btBoxShape.h>
+#include <BulletCollision/CollisionShapes/btSphereShape.h>
 #include <BulletCollision/CollisionShapes/btCompoundShape.h>
 
 //#define DEBUG_FIXED_OBJECTS
 //#define USE_BULLET_GENERIC_6DOF_CONSTRAINT
 
+#include <typeinfo>
+
 using namespace VirtualRobot;
 
 namespace SimDynamics {
@@ -33,7 +36,7 @@ BulletObject::BulletObject(VirtualRobot::SceneObjectPtr o)
 	THROW_VR_EXCEPTION_IF(!o,"NULL object");
 	CollisionModelPtr colModel = o->getCollisionModel();
 
-	if (!colModel)
+    if (!colModel)
 	{
 		VR_WARNING << "Building empty collision shape for object " << o->getName() << endl;
 		collisionShape.reset(new btEmptyShape());
@@ -42,16 +45,34 @@ BulletObject::BulletObject(VirtualRobot::SceneObjectPtr o)
 		VirtualRobot::ObstaclePtr ob = Obstacle::createBox(10.0f,10.0f,10.0f);
 		ob->setGlobalPose(o->getGlobalPose());
 		colModel = ob->getCollisionModel();*/
-	} else
+    } else
 	{
-		THROW_VR_EXCEPTION_IF(!colModel,"No CollisionModel, could not create dynamics model...");
+        THROW_VR_EXCEPTION_IF(!colModel, "No CollisionModel, could not create dynamics model...");
 
 		if (o->getName() != "Floor")
 		{
-			TriMeshModelPtr trimesh;
-			trimesh = colModel->getTriMeshModel();
-			THROW_VR_EXCEPTION_IF( ( !trimesh || trimesh->faces.size()==0) , "No TriMeshModel, could not create dynamics model...");
-			collisionShape.reset(createConvexHullShape(trimesh));
+
+            std::vector<VisualizationNode::PrimitivePtr> primitives = colModel->getVisualization()->primitives;
+            if (primitives.size() == 1)
+            {
+                collisionShape.reset(getShapeFromPrimitive(primitives[0]));
+            }
+            else if (primitives.size() > 1)
+            {
+                std::vector<VisualizationNode::PrimitivePtr>::iterator it;
+                btCompoundShape *compoundShape = new btCompoundShape();
+                for (it = primitives.begin(); it != primitives.end(); it++) {
+                    compoundShape->addChildShape(BulletEngine::getPoseBullet((*it)->transform), getShapeFromPrimitive(*it));
+                }
+                collisionShape.reset(compoundShape);
+            }
+            else
+            {
+                TriMeshModelPtr trimesh;
+                trimesh = colModel->getTriMeshModel();
+                THROW_VR_EXCEPTION_IF( ( !trimesh || trimesh->faces.size()==0) , "No TriMeshModel, could not create dynamics model...");
+                collisionShape.reset(createConvexHullShape(trimesh));
+            }
 		}
 		else
 		{
@@ -129,6 +150,30 @@ BulletObject::~BulletObject()
 	delete motionState;
 }
 
+
+btCollisionShape* BulletObject::getShapeFromPrimitive(VirtualRobot::VisualizationNode::PrimitivePtr primitive)
+{
+    btCollisionShape* result;
+    if (primitive->type == VisualizationNode::Box::TYPE)
+    {
+        VisualizationNode::Box* box = boost::dynamic_pointer_cast<VisualizationNode::Box>(primitive).get();
+        btBoxShape *boxShape = new btBoxShape(btVector3(box->width / 1000.f, box->height / 1000.f, box->depth / 1000.f));
+        result = boxShape;
+    }
+    else if (primitive->type == VisualizationNode::Sphere::TYPE)
+    {
+        VisualizationNode::Sphere* sphere = boost::dynamic_pointer_cast<VisualizationNode::Sphere>(primitive).get();
+        btSphereShape *sphereShape = new btSphereShape(btScalar(sphere->radius / 1000.f));
+        result = sphereShape;
+    }
+    else
+    {
+        VR_ERROR << "Unsupported shape type " << primitive->type << std::endl;
+        result = new btEmptyShape();
+    }
+    return result;
+}
+
 btConvexHullShape* BulletObject::createConvexHullShape(VirtualRobot::TriMeshModelPtr trimesh)
 {
 	VR_ASSERT(trimesh);
diff --git a/SimDynamics/DynamicsEngine/BulletEngine/BulletObject.h b/SimDynamics/DynamicsEngine/BulletEngine/BulletObject.h
index 99d0cc95617d8b6c1ffad71d91fb2d1058937894..79a70048c652f6c3ca527b8c7564f61892f13056 100644
--- a/SimDynamics/DynamicsEngine/BulletEngine/BulletObject.h
+++ b/SimDynamics/DynamicsEngine/BulletEngine/BulletObject.h
@@ -84,11 +84,12 @@ public:
 protected:
 
     void setPoseIntern(const Eigen::Matrix4f &pose);
+    btCollisionShape* getShapeFromPrimitive(VirtualRobot::VisualizationNode::PrimitivePtr primitive);
 
 	btConvexHullShape* createConvexHullShape(VirtualRobot::TriMeshModelPtr trimesh);
 
 	boost::shared_ptr<btRigidBody> rigidBody;
-	boost::shared_ptr<btCollisionShape> collisionShape; // bullet collision shape
+    boost::shared_ptr<btCollisionShape> collisionShape; // bullet collision shape
 	
 	Eigen::Vector3f com; // com offset of trimesh
 
diff --git a/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.cpp b/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.cpp
index c71c0ad8226f142f5434705d4312333e9a7f9170..9ce1e4812b800efe94b4fb054681c8cd07e58132 100644
--- a/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.cpp
+++ b/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.cpp
@@ -66,6 +66,21 @@ SimDynamicsWindow::SimDynamicsWindow(std::string &sRobotFilename, Qt::WFlags fla
     dynamicsObject->setPosition(Eigen::Vector3f(1000,2000,1000.0f));
 	dynamicsWorld->addObject(dynamicsObject);
 
+    ManipulationObjectPtr vitalis;
+    std::string vitalisPath = "objects/VitalisWithPrimitives.xml";
+    if (VirtualRobot::RuntimeEnvironment::getDataFileAbsolute(vitalisPath))
+    {
+        vitalis = ObjectIO::loadManipulationObject(vitalisPath);
+    }
+    if (vitalis)
+    {
+        vitalis->setMass(0.5f);
+        dynamicsObjectVitalis = dynamicsWorld->CreateDynamicsObject(vitalis);
+        dynamicsObjectVitalis->setPosition(Eigen::Vector3f(-1000.f, 2000.f, 1000.f));
+        dynamicsWorld->addObject(dynamicsObjectVitalis);
+    }
+
+
 #if 0
     std::string f = "/home/niko/coding/armarx/SimulationX/data/environment/KIT_Robot_Kitchen.xml";
     ManipulationObjectPtr mo = ObjectIO::loadManipulationObject(f);
@@ -193,6 +208,8 @@ void SimDynamicsWindow::buildVisualization()
 	SceneObject::VisualizationType colModel = useColModel?SceneObject::Collision:SceneObject::Full;
 	viewer->addVisualization(dynamicsRobot,colModel);
     viewer->addVisualization(dynamicsObject,colModel);
+    if (dynamicsObjectVitalis)
+        viewer->addVisualization(dynamicsObjectVitalis,colModel);
     if (dynamicsObject2)
         viewer->addVisualization(dynamicsObject2,colModel);
 }
diff --git a/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.h b/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.h
index 2ceafa1731328c091cdd2e979b2ef85d9868a7c1..4a52c93c2955fa7a024419efad96024bbc25cb33 100644
--- a/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.h
+++ b/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.h
@@ -75,6 +75,7 @@ protected:
 	SimDynamics::DynamicsRobotPtr dynamicsRobot;
 	SimDynamics::DynamicsObjectPtr dynamicsObject;
     SimDynamics::DynamicsObjectPtr dynamicsObject2;
+    SimDynamics::DynamicsObjectPtr dynamicsObjectVitalis;
 
 	Ui::MainWindowBulletViewer UI;
 
diff --git a/VirtualRobot/Visualization/CoinVisualization/CoinVisualizationNode.cpp b/VirtualRobot/Visualization/CoinVisualization/CoinVisualizationNode.cpp
index 4204acf3dad4223f6370c410058a04b004a683bc..4e93095f217c58d05d3afa6962190bbb385b8e04 100644
--- a/VirtualRobot/Visualization/CoinVisualization/CoinVisualizationNode.cpp
+++ b/VirtualRobot/Visualization/CoinVisualization/CoinVisualizationNode.cpp
@@ -37,7 +37,7 @@ CoinVisualizationNode::CoinVisualizationNode(SoNode* visualizationNode) :
 	visualizationAtGlobalPose->ref();
 	
 	globalPoseTransform = new SoMatrixTransform();
-	visualizationAtGlobalPose->addChild(globalPoseTransform);
+    visualizationAtGlobalPose->addChild(globalPoseTransform);
 	
 	attachedVisualizationsSeparator = new SoSeparator();
 	attachedVisualizationsSeparator->ref();
@@ -243,7 +243,7 @@ void CoinVisualizationNode::attachVisualization(const std::string &name, Visuali
 	if (coinVisualizationNode && coinVisualizationNode->getCoinVisualization())
 	{
 		attachedCoinVisualizations[name] = coinVisualizationNode->getCoinVisualization();
-		attachedVisualizationsSeparator->addChild(coinVisualizationNode->getCoinVisualization());
+        attachedVisualizationsSeparator->addChild(coinVisualizationNode->getCoinVisualization());
 	}
 }
 
diff --git a/VirtualRobot/Visualization/VisualizationNode.cpp b/VirtualRobot/Visualization/VisualizationNode.cpp
index 6934be4a933c16f1fb96dddd52640aa43412e1fc..206a5e8584337f525315ac7934d5c49d6acb7cfa 100644
--- a/VirtualRobot/Visualization/VisualizationNode.cpp
+++ b/VirtualRobot/Visualization/VisualizationNode.cpp
@@ -204,5 +204,4 @@ void VisualizationNode::scale( Eigen::Vector3f &scaleFactor )
 	VR_WARNING << "not implemented..." << endl;
 }
 
-
 } // namespace VirtualRobot
diff --git a/VirtualRobot/Visualization/VisualizationNode.h b/VirtualRobot/Visualization/VisualizationNode.h
index e7ae7b34fc2c2c284347d6eb50f24e80a489a940..5bd62722c5670eb0f60ac1cd04c81ce8bf551d33 100644
--- a/VirtualRobot/Visualization/VisualizationNode.h
+++ b/VirtualRobot/Visualization/VisualizationNode.h
@@ -39,6 +39,34 @@ class VIRTUAL_ROBOT_IMPORT_EXPORT VisualizationNode
 public:
 	EIGEN_MAKE_ALIGNED_OPERATOR_NEW
 
+    struct Primitive {
+        static const int TYPE = 0;
+        Primitive() : type(TYPE), transform(Eigen::Matrix4f::Identity()) {}
+        virtual ~Primitive() {} //needed for dynamic cast to work
+        Eigen::Matrix4f transform;
+        const int type;
+    protected:
+        Primitive(int type) : type(type) {}
+    };
+
+    struct Box : public Primitive {
+        static const int TYPE = 1;
+        Box() : Primitive(TYPE) {}
+        float width;
+        float height;
+        float depth;
+    };
+
+    struct Sphere : public Primitive {
+        static const int TYPE = 2;
+        Sphere() : Primitive(TYPE) {}
+        float radius;
+    };
+
+    typedef boost::shared_ptr<Primitive> PrimitivePtr;
+
+    std::vector<PrimitivePtr> primitives;
+
 	/*!
 	Constructor
 	*/
diff --git a/VirtualRobot/XML/BaseIO.cpp b/VirtualRobot/XML/BaseIO.cpp
index 0b58727c262ea6db36009820c08ad288897279ce..37025ac1802f61b09e1aa1159404de2b5ba0a8a0 100644
--- a/VirtualRobot/XML/BaseIO.cpp
+++ b/VirtualRobot/XML/BaseIO.cpp
@@ -712,6 +712,7 @@ VisualizationNodePtr BaseIO::processVisualizationTag(rapidxml::xml_node<char> *v
 	std::string visuFileType = "";
 	std::string visuFile = "";
 	rapidxml::xml_attribute<> *attr;
+    std::vector<VisualizationNode::PrimitivePtr> primitives;
 	VisualizationNodePtr visualizationNode;
 
 	if (!visuXMLNode)
@@ -749,14 +750,68 @@ VisualizationNodePtr BaseIO::processVisualizationTag(rapidxml::xml_node<char> *v
 			//visuFile = visuFileXMLNode->value();
 			//makeAbsolutePath(basePath,visuFile);
 		}
-		if (visuFile!="")
+
+        rapidxml::xml_node<> *visuPrimitivesXMLNode = visuXMLNode->first_node("primitives",0,false);
+        if (visuPrimitivesXMLNode)
+        {
+            rapidxml::xml_node<> *primitiveXMLNode = visuPrimitivesXMLNode->first_node();
+
+            while (primitiveXMLNode)
+            {
+                //extract info
+                std::string pName = primitiveXMLNode->name();
+                VisualizationNode::PrimitivePtr primitive;
+
+                float lenFactor = 1.f;
+                if (hasUnitsAttribute(primitiveXMLNode))
+                {
+                    Units u = getUnitsAttribute(primitiveXMLNode,Units::eLength);
+                    if (u.isMeter())
+                    {
+                        lenFactor = 1000.f;
+                    }
+                }
+
+                if (pName == "Box")
+                {
+                    VisualizationNode::Box *box = new VisualizationNode::Box;
+                    box->width = convertToFloat(primitiveXMLNode->first_attribute("width",0,false)->value()) * lenFactor;
+                    box->height = convertToFloat(primitiveXMLNode->first_attribute("height",0,false)->value()) * lenFactor;
+                    box->depth = convertToFloat(primitiveXMLNode->first_attribute("depth",0,false)->value()) * lenFactor;
+                    primitive.reset(box);
+                } else if (pName == "Sphere")
+                {
+                    VisualizationNode::Sphere *sphere = new VisualizationNode::Sphere;
+                    sphere->radius = convertToFloat(primitiveXMLNode->first_attribute("radius",0,false)->value()) * lenFactor;
+                    primitive.reset(sphere);
+                } else
+                {
+                    VR_ERROR << "Unknown primitive type \"" << pName << "\"; skipping";
+                }
+
+                if (primitive)
+                {
+                    Eigen::Matrix4f transform;
+                    processTransformNode(primitiveXMLNode->first_node("transform",0,false), "transform", transform);
+                    primitive->transform = transform;
+                    primitives.push_back(primitive);
+                }
+
+                primitiveXMLNode = primitiveXMLNode->next_sibling();
+            }
+        }
+
+        if (visuFile!="")
 		{
 			VisualizationFactoryPtr visualizationFactory = VisualizationFactory::fromName(visuFileType, NULL);
-			if (visualizationFactory)
-				visualizationNode = visualizationFactory->getVisualizationFromFile(visuFile);
-			else
+            if (visualizationFactory)
+            {
+                visualizationNode = visualizationFactory->getVisualizationFromFile(visuFile);
+                visualizationNode->primitives = primitives;
+            } else
 				VR_WARNING << "VisualizationFactory of type '" << visuFileType << "' not present. Ignoring Visualization data in Node <" << tagName << ">" << endl;
-		}
+        }
+
 
 		rapidxml::xml_node<> *coordXMLNode = visuXMLNode->first_node("coordinateaxis",0,false);
 		if (coordXMLNode)
@@ -862,8 +917,8 @@ CollisionModelPtr BaseIO::processCollisionTag(rapidxml::xml_node<char> *colXMLNo
 			{
 				bbox = isTrue(attr->value());
 			}
-
 		}
+
 		if (collisionFile!="")
 		{
 			VisualizationFactoryPtr visualizationFactory = VisualizationFactory::fromName(collisionFileType, NULL);
diff --git a/VirtualRobot/XML/ObjectIO.cpp b/VirtualRobot/XML/ObjectIO.cpp
index 1cc246a314037778527d0b24b06237646a183696..0200ff23d7faa279e90188d28776dcde6d553062 100644
--- a/VirtualRobot/XML/ObjectIO.cpp
+++ b/VirtualRobot/XML/ObjectIO.cpp
@@ -231,6 +231,8 @@ ManipulationObjectPtr ObjectIO::processManipulationObject(rapidxml::xml_node<cha
 		{
 			THROW_VR_EXCEPTION_IF(colProcessed, "Two collision tags defined in ManipulationObject '" << objName << "'." << endl);
 			collisionModel = processCollisionTag(node, objName, basePath);
+            if (collisionModel && visualizationNode)
+                collisionModel->getVisualization()->primitives = visualizationNode->primitives;
 			colProcessed = true;
 		} else if (nodeName == "physics")
 		{
@@ -327,6 +329,8 @@ ObstaclePtr ObjectIO::processObstacle(rapidxml::xml_node<char>* objectXMLNode, c
 		{
 			THROW_VR_EXCEPTION_IF(colProcessed, "Two collision tags defined in Obstacle '" << objName << "'." << endl);
 			collisionModel = processCollisionTag(node, objName, basePath);
+            if (collisionModel && visualizationNode)
+                collisionModel->getVisualization()->primitives = visualizationNode->primitives;
 			colProcessed = true;
 		} else if (nodeName == "physics")
 		{